aboutsummaryrefslogtreecommitdiff
path: root/.emacs.d
diff options
context:
space:
mode:
authorRaúl Benencia <id@rbenencia.name>2023-07-20 07:53:35 -0700
committerRaúl Benencia <id@rbenencia.name>2023-07-22 10:45:18 -0700
commit5860445da55ac3abc3935c6ffd5e9bb4539225c9 (patch)
tree2de3124b4c0577245a0b7e1dec30732af7fcc191 /.emacs.d
parentfd0754be08f4b2f9ef58625c17544a238afefade (diff)
emacs: move everything to ~/.emacs.d
Diffstat (limited to '.emacs.d')
-rw-r--r--.emacs.d/early-init.el20
-rw-r--r--.emacs.d/init.el178
-rw-r--r--.emacs.d/rul-init.d/auto-fill.el4
-rw-r--r--.emacs.d/rul-init.d/company.el42
-rw-r--r--.emacs.d/rul-init.d/dashboard.el9
-rw-r--r--.emacs.d/rul-init.d/doom-modeline.el11
-rw-r--r--.emacs.d/rul-init.d/flycheck.el20
-rw-r--r--.emacs.d/rul-init.d/flyspell.el12
-rw-r--r--.emacs.d/rul-init.d/fonts.el31
-rw-r--r--.emacs.d/rul-init.d/go-lang.el23
-rw-r--r--.emacs.d/rul-init.d/hydra.el97
-rw-r--r--.emacs.d/rul-init.d/ibuffer.el35
-rw-r--r--.emacs.d/rul-init.d/imenu.el12
-rw-r--r--.emacs.d/rul-init.d/ivy.el38
-rw-r--r--.emacs.d/rul-init.d/latex.el9
-rw-r--r--.emacs.d/rul-init.d/logos.el29
-rw-r--r--.emacs.d/rul-init.d/lsp.el17
-rw-r--r--.emacs.d/rul-init.d/magit.el15
-rw-r--r--.emacs.d/rul-init.d/mail-mode.el15
-rw-r--r--.emacs.d/rul-init.d/markdown.el5
-rw-r--r--.emacs.d/rul-init.d/mu4e.el61
-rw-r--r--.emacs.d/rul-init.d/notmuch.el133
-rw-r--r--.emacs.d/rul-init.d/projectile.el8
-rw-r--r--.emacs.d/rul-init.d/python.el1
-rw-r--r--.emacs.d/rul-init.d/sml.el7
-rw-r--r--.emacs.d/rul-init.d/staging.el158
-rw-r--r--.emacs.d/rul-init.d/tabbar.el25
-rw-r--r--.emacs.d/rul-init.d/themes.el47
-rw-r--r--.emacs.d/rul-init.d/vterm.el6
-rw-r--r--.emacs.d/rul-init.d/which-key.el5
-rw-r--r--.emacs.d/rul-init.d/writeroom.el34
-rw-r--r--.emacs.d/rul-lisp/config/rul-config-elfeed.el2
-rw-r--r--.emacs.d/rul-lisp/config/rul-config-mail.el1
-rw-r--r--.emacs.d/rul-lisp/config/rul-config-org.el22
-rw-r--r--.emacs.d/rul-lisp/packages/rul-dart.el7
-rw-r--r--.emacs.d/rul-lisp/packages/rul-elfeed.el5
-rw-r--r--.emacs.d/rul-lisp/packages/rul-org-agenda.el417
-rw-r--r--.emacs.d/rul-lisp/packages/rul-org-journal.el11
-rw-r--r--.emacs.d/rul-lisp/packages/rul-org-notify.el9
-rw-r--r--.emacs.d/rul-lisp/packages/rul-org-roam.el24
-rw-r--r--.emacs.d/rul-lisp/packages/rul-org.el156
41 files changed, 1761 insertions, 0 deletions
diff --git a/.emacs.d/early-init.el b/.emacs.d/early-init.el
new file mode 100644
index 0000000..495c277
--- /dev/null
+++ b/.emacs.d/early-init.el
@@ -0,0 +1,20 @@
+(menu-bar-mode -1)
+(tool-bar-mode -1)
+(scroll-bar-mode -1)
+
+;; Initialise installed packages
+(setq package-enable-at-startup t)
+
+;; Do not report warning errors
+(setq native-comp-async-report-warnings-errors 'silent)
+
+;; Truly maximize screen
+(setq frame-resize-pixelwise t)
+
+;; Start maximized
+(add-to-list 'default-frame-alist '(fullscreen . maximized))
+
+;; No need for titlebar
+(modify-frame-parameters nil '((undecorated . t)))
+
+;;; early-init.el ends here
diff --git a/.emacs.d/init.el b/.emacs.d/init.el
new file mode 100644
index 0000000..5d0996e
--- /dev/null
+++ b/.emacs.d/init.el
@@ -0,0 +1,178 @@
+;; Debian packages: elpa-use-package elpa-fill-column-indicator fonts-hack
+
+(require 'package)
+(require 'fill-column-indicator)
+
+;; This is only needed once, near the top of the file
+(eval-when-compile
+ (require 'use-package))
+
+(add-to-list 'package-archives
+ '("melpa-stable" . "https://stable.melpa.org/packages/") t)
+
+(add-to-list 'package-archives
+ '("melpa" . "https://melpa.org/packages/") t)
+
+;; Do not persist customizations
+(setq custom-file (make-temp-file "emacs-custom-"))
+
+;; Place backups in ~/.backups/ directory, like a civilized program.
+;; ------
+(if (file-directory-p "~/.backup")
+ (setq backup-directory-alist '(("." . "~/.backup")))
+ (message "Directory does not exist: ~/.backup"))
+
+(filesets-init)
+
+(setq backup-by-copying t ; Don't delink hardlinks
+ delete-old-versions t ; Clean up the backups
+ version-control t ; Use version numbers on backups,
+ kept-new-versions 3 ; keep some new versions
+ kept-old-versions 2) ; and some old ones, too
+
+;; ---------
+;; Generic keybindings
+;; ---------
+(global-set-key (kbd "C-c d") 'diff-buffer-with-file)
+(global-set-key (kbd "C-c R") 'revert-buffer)
+
+;; compile
+(global-set-key [f12] 'compile)
+
+(defun help/insert-em-dash ()
+ "Inserts an EM-DASH (not a HYPEN, not an N-DASH)"
+ (interactive)
+ (insert "—"))
+
+(global-set-key (kbd "C--") #'help/insert-em-dash)
+
+;; ------
+;; General config
+;; ------
+
+(setq fill-column 79)
+
+;; Make sure that pressing middle mouse button pastes right at point,
+;; not where the mouse cursor is.
+(setq mouse-yank-at-point t)
+
+(setq column-number-mode 1)
+(setq line-number-mode 1)
+(setq-default indent-tabs-mode nil)
+(setq-default tab-width 4)
+
+(setq-default c-basic-offset 4)
+
+;; ------
+;; Initialize environment
+;; ------
+
+
+(setenv "TMPDIR" (concat (getenv "HOME") "/tmp"))
+(server-start)
+
+;; ------
+;; Helper for compilation.
+;; ------
+;; Close the compilation window if there was no error at all.
+(defun compilation-exit-autoclose (status code msg)
+ ;; If M-x compile exists with a 0
+ (when (and (eq status 'exit) (zerop code))
+ ;; then bury the *compilation* buffer, so that C-x b doesn't go there
+ (bury-buffer)
+ ;; and delete the *compilation* window
+ (delete-window (get-buffer-window (get-buffer "*compilation*"))))
+ ;; Always return the anticipated result of compilation-exit-message-function
+ (cons msg code))
+
+;; Specify my function (maybe I should have done a lambda function)
+(setq compilation-exit-message-function 'compilation-exit-autoclose)
+(setq compilation-read-command nil)
+
+;; Themes
+(add-to-list 'custom-theme-load-path "~/.emacs.d/themes/")
+
+;; Remove scratch message
+(setq initial-scratch-message "")
+
+;; Ask y or n instead of yes or no
+(defalias 'yes-or-no-p 'y-or-n-p)
+
+;; Fancier buffer selection
+(global-set-key (kbd "C-x C-b") 'bs-show)
+
+;;; Stefan Monnier <foo at acm.org>. It is the opposite of fill-paragraph
+(defun unfill-paragraph (&optional region)
+ "Takes a multi-line paragraph and makes it into a single line of text."
+ (interactive (progn (barf-if-buffer-read-only) '(t)))
+ (let ((fill-column (point-max))
+ ;; This would override `fill-column' if it's an integer.
+ (emacs-lisp-docstring-fill-column t))
+ (fill-paragraph nil region)))
+
+;; Handy key definition
+(define-key global-map "\M-Q" 'unfill-paragraph)
+
+;; Only flash the mode line
+(setq ring-bell-function
+ (lambda ()
+ (let ((orig-fg (face-foreground 'mode-line)))
+ (set-face-foreground 'mode-line "#F2804F")
+ (run-with-idle-timer 0.1 nil
+ (lambda (fg) (set-face-foreground 'mode-line fg))
+ orig-fg))))
+
+;; Highlight parens
+(setq show-paren-delay 0)
+(show-paren-mode 1)
+
+;; Save what you enter into minibuffer prompts
+(setq history-length 25)
+(savehist-mode 1)
+
+;; Remember and restore cursor information
+(save-place-mode 1)
+
+;; Set this to t if you don't understand what it means
+(setq vc-follow-symlinks nil)
+
+(dolist (path '("~/.emacs.d/rul-lisp/config" "~/.emacs.d/rul-lisp/packages"))
+ (add-to-list 'load-path path))
+
+(require 'rul-org)
+(require 'rul-org-roam)
+(require 'rul-elfeed)
+(require 'rul-dart)
+
+(load-file "~/.emacs.d/rul-init.d/fonts.el")
+(load-file "~/.emacs.d/rul-init.d/themes.el")
+
+;; Init parts (will be deprecated in favor of packages)
+(load-file "~/.emacs.d/rul-init.d/auto-fill.el")
+;(load-file "~/.emacs.d/rul-init.d/doom-modeline.el")
+(load-file "~/.emacs.d/rul-init.d/flycheck.el")
+(load-file "~/.emacs.d/rul-init.d/flyspell.el")
+(load-file "~/.emacs.d/rul-init.d/go-lang.el")
+(load-file "~/.emacs.d/rul-init.d/hydra.el")
+(load-file "~/.emacs.d/rul-init.d/ibuffer.el")
+(load-file "~/.emacs.d/rul-init.d/imenu.el")
+;(load-file "~/.emacs.d/rul-init.d/ivy.el")
+(load-file "~/.emacs.d/rul-init.d/latex.el")
+(load-file "~/.emacs.d/rul-init.d/logos.el")
+(load-file "~/.emacs.d/rul-init.d/mail-mode.el")
+(load-file "~/.emacs.d/rul-init.d/markdown.el")
+(load-file "~/.emacs.d/rul-init.d/magit.el")
+(load-file "~/.emacs.d/rul-init.d/notmuch.el")
+(load-file "~/.emacs.d/rul-init.d/projectile.el")
+(load-file "~/.emacs.d/rul-init.d/tabbar.el")
+(load-file "~/.emacs.d/rul-init.d/which-key.el")
+(load-file "~/.emacs.d/rul-init.d/writeroom.el")
+(load-file "~/.emacs.d/rul-init.d/vterm.el")
+
+(load-file "~/.emacs.d/rul-init.d/staging.el")
+
+(when-let* ((file (locate-user-emacs-file "rul-pre-init.el"))
+ ((file-exists-p file)))
+ (load-file file))
+
+;; init.el ends here
diff --git a/.emacs.d/rul-init.d/auto-fill.el b/.emacs.d/rul-init.d/auto-fill.el
new file mode 100644
index 0000000..dad2831
--- /dev/null
+++ b/.emacs.d/rul-init.d/auto-fill.el
@@ -0,0 +1,4 @@
+;; auto-fill mode
+(add-hook 'text-mode-hook 'turn-on-auto-fill)
+(global-set-key (kbd "C-c q") 'auto-fill-mode)
+
diff --git a/.emacs.d/rul-init.d/company.el b/.emacs.d/rul-init.d/company.el
new file mode 100644
index 0000000..d52000e
--- /dev/null
+++ b/.emacs.d/rul-init.d/company.el
@@ -0,0 +1,42 @@
+(use-package company
+ :ensure t
+ :defer t
+ :init (global-company-mode)
+ :config
+ (progn
+ ;; Use Company for completion
+ (bind-key [remap completion-at-point] #'company-complete company-mode-map)
+
+ (setq company-tooltip-align-annotations t
+ ;; Easy navigation to candidates with M-<n>
+ company-show-numbers t)
+ (setq company-dabbrev-downcase nil))
+
+ (setq company-idle-delay 0)
+ (setq company-minimum-prefix-length 1)
+ :diminish company-mode)
+
+(use-package company-quickhelp ; Documentation popups for Company
+ :ensure t
+ :defer t
+ :init (add-hook 'global-company-mode-hook #'company-quickhelp-mode))
+
+(use-package company-go
+ :ensure t
+ :defer t
+ :init
+ (with-eval-after-load 'company
+ (add-to-list 'company-backends 'company-go)))
+
+(use-package company-lsp
+ :ensure t
+ :commands company-lsp)
+
+(use-package yasnippet
+ :ensure t
+ :config
+ (yas-global-mode 1)
+ (global-set-key (kbd "C-c y") 'company-yasnippet))
+
+(use-package yasnippet-snippets
+ :ensure t)
diff --git a/.emacs.d/rul-init.d/dashboard.el b/.emacs.d/rul-init.d/dashboard.el
new file mode 100644
index 0000000..7bf51a9
--- /dev/null
+++ b/.emacs.d/rul-init.d/dashboard.el
@@ -0,0 +1,9 @@
+(use-package dashboard
+ :ensure t
+ :diminish dashboard-mode
+ :config
+ (setq dashboard-banner-logo-title "Happy hacking!")
+ (setq dashboard-items '((recents . 10)
+ (projects . 5)
+ (bookmarks . 10)))
+ (dashboard-setup-startup-hook))
diff --git a/.emacs.d/rul-init.d/doom-modeline.el b/.emacs.d/rul-init.d/doom-modeline.el
new file mode 100644
index 0000000..b212652
--- /dev/null
+++ b/.emacs.d/rul-init.d/doom-modeline.el
@@ -0,0 +1,11 @@
+;; Elpa packages: doom-modeline all-the-icons
+;; Run: all-the-icons-install-fonts
+
+(use-package doom-modeline
+ :ensure t
+ :hook (after-init . doom-modeline-mode)
+ :config
+ (setq doom-modeline-height 1)
+ (set-face-attribute 'mode-line nil :family "Noto Sans" :height 150)
+ (set-face-attribute 'mode-line-inactive nil :family "Noto Sans" :height 150)
+)
diff --git a/.emacs.d/rul-init.d/flycheck.el b/.emacs.d/rul-init.d/flycheck.el
new file mode 100644
index 0000000..6662c06
--- /dev/null
+++ b/.emacs.d/rul-init.d/flycheck.el
@@ -0,0 +1,20 @@
+;; Debian-packages: elpa-flycheck python3-proselint
+
+(flycheck-define-checker proselint
+ "A linter for prose."
+ :command ("proselint" source-inplace)
+ :error-patterns
+ ((warning line-start (file-name) ":" line ":" column ": "
+ (id (one-or-more (not (any " "))))
+ (message) line-end))
+ :modes (text-mode markdown-mode gfm-mode org-mode))
+
+(add-to-list 'flycheck-checkers 'proselint)
+
+;; TODO: docker run --rm -p 8010:8010 erikvl87/languagetool
+(use-package flycheck-languagetool
+ :ensure t
+ :hook (message-mode . flycheck-languagetool-setup)
+ :init
+ (setq flycheck-languagetool-url "http://localhost:8010")
+)
diff --git a/.emacs.d/rul-init.d/flyspell.el b/.emacs.d/rul-init.d/flyspell.el
new file mode 100644
index 0000000..8cf27b8
--- /dev/null
+++ b/.emacs.d/rul-init.d/flyspell.el
@@ -0,0 +1,12 @@
+(defcustom flyspell-delayed-commands nil
+ "List of commands that are \"delayed\" for Flyspell mode.
+After these commands, Flyspell checking is delayed for a short time,
+whose length is specified by `flyspell-delay'."
+ :group 'flyspell
+ :type '(repeat (symbol)))
+
+(setq ispell-dictionary "en")
+(setq flyspell-default-dictionary "en")
+
+(setq flyspell-issue-welcome-flag nil)
+(setq-default ispell-list-command "list")
diff --git a/.emacs.d/rul-init.d/fonts.el b/.emacs.d/rul-init.d/fonts.el
new file mode 100644
index 0000000..69eb304
--- /dev/null
+++ b/.emacs.d/rul-init.d/fonts.el
@@ -0,0 +1,31 @@
+;; elpa-packages: fontaine
+
+(setq fontaine-presets
+ '((tiny
+ :default-family "Fira Code Retina"
+ :default-height 100)
+ (small
+ :default-family "Fira Code Retina"
+ :default-height 120)
+ (medium
+ :default-height 140)
+ (large
+ :default-weight semilight
+ :default-height 180
+ :bold-weight extrabold)
+ (presentation
+ :default-weight semilight
+ :default-height 200
+ :bold-weight extrabold)
+ (jumbo
+ :default-weight semilight
+ :default-height 230
+ :bold-weight extrabold)
+ (t
+ :default-family "Fira Code Retina"
+ :default-weight regular
+ :default-height 140
+ :variable-pitch-family "Fira Code Retina")))
+
+;; Set desired style from `fontaine-presets'
+(fontaine-set-preset 'medium)
diff --git a/.emacs.d/rul-init.d/go-lang.el b/.emacs.d/rul-init.d/go-lang.el
new file mode 100644
index 0000000..8ec678b
--- /dev/null
+++ b/.emacs.d/rul-init.d/go-lang.el
@@ -0,0 +1,23 @@
+;; Debian packages: elpa-go-mode
+;; Elpa packages: go-eldoc
+
+(use-package go-mode
+ :ensure t
+ :init
+ (progn
+ (bind-key [remap find-tag] #'godef-jump))
+ :config
+ (add-hook 'go-mode-hook #'yas-minor-mode)
+ (add-hook 'go-mode-hook 'electric-pair-mode)
+ (add-hook 'go-mode-hook 'my-go-mode-hook)
+ (add-hook 'before-save-hook 'gofmt-before-save)
+)
+
+(use-package go-eldoc
+ :ensure t
+ :init
+ (add-hook 'go-mode-hook 'go-eldoc-setup))
+
+;; Define function to call when go-mode loads
+(defun my-go-mode-hook ()
+ (set 'compile-command "go build -v && go test -v && go vet"))
diff --git a/.emacs.d/rul-init.d/hydra.el b/.emacs.d/rul-init.d/hydra.el
new file mode 100644
index 0000000..8afe86f
--- /dev/null
+++ b/.emacs.d/rul-init.d/hydra.el
@@ -0,0 +1,97 @@
+(use-package hydra
+ :defer 1)
+
+;; projectile
+(defhydra hydra-projectile-other-window (:color teal)
+ "projectile-other-window"
+ ("f" projectile-find-file-other-window "file")
+ ("g" projectile-find-file-dwim-other-window "file dwim")
+ ("d" projectile-find-dir-other-window "dir")
+ ("b" projectile-switch-to-buffer-other-window "buffer")
+ ("q" nil "cancel" :color blue))
+
+(defhydra hydra-projectile (:color teal
+ :hint nil)
+ "
+ PROJECTILE: %(projectile-project-root)
+
+ Find File Search/Tags Buffers Cache
+------------------------------------------------------------------------------------------
+_s-f_: file _a_: ag _i_: Ibuffer _c_: cache clear
+ _ff_: file dwim _g_: update gtags _b_: switch to buffer _x_: remove known project
+ _fd_: file curr dir _o_: multi-occur _s-k_: Kill all buffers _X_: cleanup non-existing
+ _r_: recent file _s_: ripgrep ^^^^_z_: cache current
+ _d_: dir
+
+"
+ ("a" projectile-ag)
+ ("b" projectile-switch-to-buffer)
+ ("c" projectile-invalidate-cache)
+ ("d" projectile-find-dir)
+ ("s-f" projectile-find-file)
+ ("ff" projectile-find-file-dwim)
+ ("fd" projectile-find-file-in-directory)
+ ("g" ggtags-update-tags)
+ ("s-g" ggtags-update-tags)
+ ("i" projectile-ibuffer)
+ ("K" projectile-kill-buffers)
+ ("s-k" projectile-kill-buffers)
+ ("m" projectile-multi-occur)
+ ("o" projectile-multi-occur)
+ ("s-p" projectile-switch-project "switch project")
+ ("p" projectile-switch-project)
+ ("s" projectile-save-project-buffers "save project buffers")
+ ("r" projectile-recentf)
+ ("x" projectile-remove-known-project)
+ ("X" projectile-cleanup-known-projects)
+ ("z" projectile-cache-current-file)
+ ("`" hydra-projectile-other-window/body "other window")
+ ("q" nil "cancel" :color blue))
+
+
+(global-set-key (kbd "C-c p") 'hydra-projectile/body)
+
+;; tab-bar
+(defhydra hydra-tab-bar (:color amaranth)
+ "Tab Bar Operations"
+ ("t" tab-new "Create a new tab" :column "Creation" :exit t)
+ ("d" dired-other-tab "Open Dired in another tab")
+ ("f" find-file-other-tab "Find file in another tab")
+ ("x" tab-close "Close current tab")
+ ("m" tab-move "Move current tab" :column "Management")
+ ("r" tab-rename "Rename Tab")
+ ("<return>" tab-bar-select-tab-by-name "Select tab by name" :column "Navigation")
+ ("l" tab-next "Next Tab")
+ ("j" tab-previous "Previous Tab")
+ ("q" nil "Exit" :exit t))
+
+(global-set-key (kbd "C-x t") 'hydra-tab-bar/body)
+
+;; Zoom
+(defhydra hydra-zoom ()
+ "zoom"
+ ("g" text-scale-increase "in")
+ ("l" text-scale-decrease "out"))
+
+(global-set-key (kbd "C-c z") 'hydra-zoom/body)
+
+;; Go
+(defhydra hydra-go ()
+ "zoom"
+ ("=" gofmt :exit t)
+ ("c" go-coverage :exit t))
+
+;; vterm
+(defhydra hydra-vterm ()
+ "zoom"
+ ("t" multi-vterm "Open a terminal" :exit t)
+ ("d" multi-vterm-dedicated-open "Dedicated" :exit t)
+ ("p" multi-vterm-prev "Previous terminal")
+ ("n" multi-vterm-next "Next terminal")
+ ("r" multi-vterm-rename-buffer "Rename buffer" :exit t)
+ )
+
+(global-set-key (kbd "C-c t") 'hydra-vterm/body)
+
+
+(global-set-key (kbd "C-c m") 'hydra-go/body)
diff --git a/.emacs.d/rul-init.d/ibuffer.el b/.emacs.d/rul-init.d/ibuffer.el
new file mode 100644
index 0000000..d5198d8
--- /dev/null
+++ b/.emacs.d/rul-init.d/ibuffer.el
@@ -0,0 +1,35 @@
+;; Debian packages: elpa-ibuffer-vc
+
+(use-package ibuffer ; Better buffer list
+ :bind (([remap list-buffers] . ibuffer))
+ ;; Show VC Status in ibuffer
+ :config (setq ibuffer-formats
+ '((mark modified read-only vc-status-mini " "
+ (name 18 18 :left :elide)
+ " "
+ (size 9 -1 :right)
+ " "
+ (mode 16 16 :left :elide)
+ " "
+ (vc-status 16 16 :left)
+ " "
+ filename-and-process)
+ (mark modified read-only " "
+ (name 18 18 :left :elide)
+ " "
+ (size 9 -1 :right)
+ " "
+ (mode 16 16 :left :elide)
+ " " filename-and-process)
+ (mark " "
+ (name 16 -1)
+ " " filename))))
+
+(use-package ibuffer-vc ; Group buffers by VC project and status
+ :ensure t
+ :defer t
+ :init (add-hook 'ibuffer-hook
+ (lambda ()
+ (ibuffer-vc-set-filter-groups-by-vc-root)
+ (unless (eq ibuffer-sorting-mode 'alphabetic)
+ (ibuffer-do-sort-by-alphabetic)))))
diff --git a/.emacs.d/rul-init.d/imenu.el b/.emacs.d/rul-init.d/imenu.el
new file mode 100644
index 0000000..1a2b29b
--- /dev/null
+++ b/.emacs.d/rul-init.d/imenu.el
@@ -0,0 +1,12 @@
+;; Debian packages: elpa-imenu-list
+(use-package imenu-list
+ :ensure t
+ :bind ("C-." . imenu-list-minor-mode)
+ :config
+ (setq imenu-list-focus-after-activation t)
+ (setq imenu-list-size 0.2)
+ (setq imenu-list-position 'left)
+ (add-hook 'go-mode-hook #'imenu-list-minor-mode))
+
+
+
diff --git a/.emacs.d/rul-init.d/ivy.el b/.emacs.d/rul-init.d/ivy.el
new file mode 100644
index 0000000..fcf69ca
--- /dev/null
+++ b/.emacs.d/rul-init.d/ivy.el
@@ -0,0 +1,38 @@
+(use-package ivy
+ :diminish (ivy-mode . "")
+ :init (ivy-mode 1) ; globally at startup
+
+ :bind (:map ivy-minibuffer-map
+ ("TAB" . ivy-alt-done))
+ :config
+ (setq ivy-use-virtual-buffers t)
+ (setq ivy-height 20)
+ (setq ivy-count-format "%d/%d ")
+ (setq ivy-re-builders-alist
+ '((swiper . ivy--regex-plus)
+ (t . ivy--regex-fuzzy)))
+)
+
+;; Override the basic Emacs commands
+(use-package counsel
+ :bind* ; load when pressed
+ (("M-x" . counsel-M-x)
+ ("C-s" . swiper)
+ ("C-x C-f" . counsel-find-file)
+ ("C-x C-r" . counsel-recentf) ; search for recently edited
+ ("C-c g" . counsel-git) ; search for files in git repo
+ ("C-c /" . counsel-ag) ; Use ag for regexp
+ ("C-x l" . counsel-locate)
+ ("C-x C-f" . counsel-find-file)
+ ("<f1> f" . counsel-describe-function)
+ ("<f1> v" . counsel-describe-variable)
+ ("<f1> l" . counsel-find-library)
+ ("<f2> i" . counsel-info-lookup-symbol)
+ ("<f2> u" . counsel-unicode-char)
+ ("C-c C-r" . ivy-resume))) ; Resume last Ivy-based completion
+
+(use-package ivy-hydra
+ :defer t
+ :after hydra)
+
+(provide 'init-ivy)
diff --git a/.emacs.d/rul-init.d/latex.el b/.emacs.d/rul-init.d/latex.el
new file mode 100644
index 0000000..de4de1f
--- /dev/null
+++ b/.emacs.d/rul-init.d/latex.el
@@ -0,0 +1,9 @@
+(add-hook 'latex-mode-hook 'flyspell-mode)
+(setq TeX-PDF-mode t)
+
+(defun pdfevince ()
+ (add-to-list 'TeX-output-view-style
+ '("^pdf$" "." "evince %o %(outpage)")))
+
+(add-hook 'LaTeX-mode-hook 'pdfevince t) ; AUCTeX LaTeX mode
+
diff --git a/.emacs.d/rul-init.d/logos.el b/.emacs.d/rul-init.d/logos.el
new file mode 100644
index 0000000..23d9937
--- /dev/null
+++ b/.emacs.d/rul-init.d/logos.el
@@ -0,0 +1,29 @@
+(use-package logos
+:ensure t
+:config
+
+;; If you want to use outlines instead of page breaks (the ^L)
+(setq logos-outlines-are-pages t)
+(setq logos-outline-regexp-alist
+ `((emacs-lisp-mode . "^;;;+ ")
+ (org-mode . "^\\*+ +")
+ (markdown-mode . "^\\#+ +")
+ ))
+
+;; These apply when `logos-focus-mode' is enabled. Their value is
+;; buffer-local.
+(setq-default logos-hide-mode-line t
+ logos-hide-buffer-boundaries t
+ logos-hide-fringe t
+ logos-variable-pitch nil
+ logos-buffer-read-only nil
+ logos-scroll-lock nil
+ logos-olivetti t)
+
+
+(let ((map global-map))
+ (define-key map [remap narrow-to-region] #'logos-narrow-dwim)
+ (define-key map [remap forward-page] #'logos-forward-page-dwim)
+ (define-key map [remap backward-page] #'logos-backward-page-dwim)
+ (define-key map (kbd "<f9>") #'logos-focus-mode))
+)
diff --git a/.emacs.d/rul-init.d/lsp.el b/.emacs.d/rul-init.d/lsp.el
new file mode 100644
index 0000000..a565b03
--- /dev/null
+++ b/.emacs.d/rul-init.d/lsp.el
@@ -0,0 +1,17 @@
+(use-package lsp-mode
+ :ensure t
+ :commands
+ (lsp lsp-deferred)
+ :hook
+ (dart-mode go-mode . lsp)
+ :init
+ (setq lsp-keymap-prefix "H-l")
+ )
+
+(defun lsp-go-install-save-hooks ()
+ (add-hook 'before-save-hook #'lsp-format-buffer t t)
+ (add-hook 'before-save-hook #'lsp-organize-imports t t))
+
+(use-package lsp-ui
+ :ensure t
+ :commands lsp-ui-mode)
diff --git a/.emacs.d/rul-init.d/magit.el b/.emacs.d/rul-init.d/magit.el
new file mode 100644
index 0000000..cd52e67
--- /dev/null
+++ b/.emacs.d/rul-init.d/magit.el
@@ -0,0 +1,15 @@
+;; Debian packages: elpa-magit
+
+(use-package magit
+ :ensure t
+ :defer t
+ :bind (("C-x g" . magit-status))
+ :config
+ (progn
+ (defun inkel/magit-log-edit-mode-hook ()
+ (flyspell-mode t)
+ (turn-on-auto-fill))
+ (defadvice magit-status (around magit-fullscreen activate)
+ (window-configuration-to-register :magit-fullscreen)
+ ad-do-it
+ (delete-other-windows))))
diff --git a/.emacs.d/rul-init.d/mail-mode.el b/.emacs.d/rul-init.d/mail-mode.el
new file mode 100644
index 0000000..09b04f9
--- /dev/null
+++ b/.emacs.d/rul-init.d/mail-mode.el
@@ -0,0 +1,15 @@
+(setq auto-mode-alist (append '((".*tmp/mutt.*" . message-mode)) auto-mode-alist))
+(setq auto-mode-alist (append '((".*tmp/neomutt.*" . message-mode)) auto-mode-alist))
+(add-to-list 'auto-mode-alist '("/mutt" . mail-mode))
+
+(setq mml-secure-openpgp-sign-with-sender t)
+
+(add-hook 'mail-mode-hook
+ (lambda ()
+ (font-lock-add-keywords nil
+ '(("^[ \t]*>[ \t]*>[ \t]*>.*$"
+ (0 'compilation-error))
+ ("^[ \t]*>[ \t]*>.*$"
+ (0 'compilation-column-number))
+ ("^[ \t]*>.*$"
+ (0 'comint-highlight-prompt))))))
diff --git a/.emacs.d/rul-init.d/markdown.el b/.emacs.d/rul-init.d/markdown.el
new file mode 100644
index 0000000..f035509
--- /dev/null
+++ b/.emacs.d/rul-init.d/markdown.el
@@ -0,0 +1,5 @@
+(autoload 'markdown-mode "markdown-mode.el"
+ "Major mode for editing Markdown files" t)
+
+(setq auto-mode-alist
+ (cons '("\\.mdwn" . markdown-mode) auto-mode-alist))
diff --git a/.emacs.d/rul-init.d/mu4e.el b/.emacs.d/rul-init.d/mu4e.el
new file mode 100644
index 0000000..da8b7c8
--- /dev/null
+++ b/.emacs.d/rul-init.d/mu4e.el
@@ -0,0 +1,61 @@
+(require 'mu4e)
+
+;; sending mail
+(setq message-send-mail-function 'message-send-mail-with-sendmail
+ sendmail-program "/home/lur/bin/te-msmtp"
+ user-mail-address "raul@thousandeyes.com"
+ user-full-name "Raúl Benencia")
+
+(setq mu4e-user-mail-address-list (list "raul@thousandeyes.com"))
+
+(setq message-kill-buffer-on-exit t)
+;; Use fancy chars
+(setq mu4e-use-fancy-chars t)
+;; don't save message to Sent Messages, Gmail/IMAP takes care of this
+(setq mu4e-sent-messages-behavior 'delete)
+(setq mu4e-update-interval 60) ;; update every 5 minutes
+
+;; use 'fancy' non-ascii characters in various places in mu4e
+;;(setq mu4e-use-fancy-chars t)
+
+(setq relevant-maildirs " (maildir:/INBOX OR maildir:/jira OR maildir:/news OR maildir:/git)")
+(mu4e-alert-enable-notifications)
+(mu4e-alert-set-default-style 'libnotify)
+(setq mu4e-alert-interesting-mail-query
+ (concat "flag:unread"
+ " AND NOT flag:trashed"
+ " AND" relevant-maildirs))
+
+(mu4e-alert-set-default-style 'libnotify)
+;;(add-hook 'after-init-hook #'mu4e-alert-enable-notifications)
+(add-hook 'after-init-hook #'mu4e-alert-enable-mode-line-display)
+
+(setq mu4e-bookmarks
+ `(,(make-mu4e-bookmark
+ :name "INBOX"
+ :query "maildir:/INBOX"
+ :key ?i)
+ ,(make-mu4e-bookmark
+ :name "Unread messages"
+ :query (concat "flag:unread AND NOT flag:trashed AND" relevant-maildirs)
+ :key ?u)
+ ,(make-mu4e-bookmark
+ :name "Today's messages"
+ :query (concat "date:today..now AND" relevant-maildirs)
+ :key ?t)
+ ,(make-mu4e-bookmark
+ :name "Last 7 days"
+ :query (concat "date:7d..now AND" relevant-maildirs)
+ :key ?w)
+ ,(make-mu4e-bookmark
+ :name "Today's unread logs "
+ :query (concat "date:today..now flag:unread AND NOT" relevant-maildirs)
+ :key ?l)
+ ,(make-mu4e-bookmark
+ :name "Today's logs "
+ :query (concat "date:today..now AND NOT maildir:/fim AND NOT" relevant-maildirs)
+ :key ?l))
+)
+
+;; (require 'mu4e-maildirs-extension)
+;; (mu4e-maildirs-extension)
diff --git a/.emacs.d/rul-init.d/notmuch.el b/.emacs.d/rul-init.d/notmuch.el
new file mode 100644
index 0000000..19ea823
--- /dev/null
+++ b/.emacs.d/rul-init.d/notmuch.el
@@ -0,0 +1,133 @@
+;; --------
+;; notmuch mode
+;; --------
+(require 'notmuch)
+(require 'notmuch-indicator)
+(require 'rul-config-mail)
+
+;;;; General UI
+(setq notmuch-show-logo nil
+ notmuch-column-control 1.0
+ notmuch-hello-auto-refresh t
+ notmuch-hello-recent-searches-max 20
+ notmuch-hello-thousands-separator ""
+ notmuch-show-all-tags-list t)
+
+;; Keymaps
+(defun rul/capture-mail()
+ "Capture mail to org mode."
+ (interactive)
+ (org-store-link nil)
+ (org-capture nil "m")
+ )
+
+(bind-key "c" 'rul/capture-mail notmuch-show-mode-map)
+
+(define-key notmuch-show-mode-map "R" 'notmuch-show-reply)
+(define-key notmuch-search-mode-map "R" 'notmuch-search-reply-to-thread)
+
+; Spam
+(define-key notmuch-show-mode-map "S"
+ (lambda ()
+ "mark message as spam"
+ (interactive)
+ (notmuch-show-tag (list "+spam" "-inbox" "-unread"))))
+
+(define-key notmuch-search-mode-map "S"
+ (lambda (&optional beg end)
+ "mark thread as spam"
+ (interactive (notmuch-search-interactive-region))
+ (notmuch-search-tag (list "+spam" "-inbox" "-unread") beg end)))
+
+; Archive
+(setq notmuch-archive-tags (list "-inbox" "+archive"))
+(define-key notmuch-show-mode-map "A"
+ (lambda ()
+ "archive"
+ (interactive)
+ (notmuch-show-tag (list "+archive" "-inbox" "-unread"))
+ (notmuch-refresh-this-buffer)))
+
+(define-key notmuch-search-mode-map "A"
+ (lambda (&optional beg end)
+ "archive thread"
+ (interactive (notmuch-search-interactive-region))
+ (notmuch-search-tag (list "+archive" "-inbox" "-unread") beg end)
+ (notmuch-refresh-this-buffer)))
+
+; Mark as read
+(define-key notmuch-search-mode-map "r"
+ (lambda (&optional beg end)
+ "mark thread as read"
+ (interactive (notmuch-search-interactive-region))
+ (notmuch-search-tag (list "-unread") beg end)
+ (notmuch-search-next-thread)))
+
+(define-key notmuch-search-mode-map (kbd "RET")
+ (lambda ()
+ "Show the selected thread with notmuch-tree if it has more
+than one email. Use notmuch-show otherwise."
+ (interactive)
+ (if (= (plist-get (notmuch-search-get-result) :total) 1)
+ (notmuch-search-show-thread)
+ (notmuch-tree (notmuch-search-find-thread-id)
+ notmuch-search-query-string
+ nil
+ (notmuch-prettify-subject (notmuch-search-find-subject))))))
+
+(defun color-inbox-if-unread () (interactive)
+ (save-excursion
+ (goto-char (point-min))
+ (let ((cnt (car (process-lines "notmuch" "count" "tag:inbox and tag:unread"))))
+ (when (> (string-to-number cnt) 0)
+ (save-excursion
+ (when (search-forward "inbox" (point-max) t)
+ (let* ((overlays (overlays-in (match-beginning 0) (match-end 0)))
+ (overlay (car overlays)))
+ (when overlay
+ (overlay-put overlay 'face '((:inherit bold) (:foreground "green")))))))))))
+
+(defvar notmuch-hello-refresh-count 0)
+(defun notmuch-hello-refresh-status-message ()
+ (let* ((new-count
+ (string-to-number
+ (car (process-lines notmuch-command "count"))))
+ (diff-count (- new-count notmuch-hello-refresh-count)))
+ (cond
+ ((= notmuch-hello-refresh-count 0)
+ (message "You have %s messages."
+ (notmuch-hello-nice-number new-count)))
+ ((> diff-count 0)
+ (message "You have %s more messages since last refresh."
+ (notmuch-hello-nice-number diff-count)))
+ ((< diff-count 0)
+ (message "You have %s fewer messages since last refresh."
+ (notmuch-hello-nice-number (- diff-count)))))
+ (setq notmuch-hello-refresh-count new-count)))
+
+(add-hook 'notmuch-hello-refresh-hook 'color-inbox-if-unread)
+(add-hook 'notmuch-hello-refresh-hook 'notmuch-hello-refresh-status-message)
+
+(setq notmuch-hello-sections '(notmuch-hello-insert-saved-searches
+ notmuch-hello-insert-search
+ notmuch-hello-insert-recent-searches
+ notmuch-hello-insert-alltags
+ ))
+
+;; https://git.sr.ht/~tslil/dotfiles/tree/4e51afbb/emacs/notmuch-config.el#L76-82
+(defmacro make-binds (mode-map binds argfunc &rest body)
+ "Create keybindings in `mode-map' using a list of (keystr . arg)
+pairs in `binds' of the form ( ... (argfunc arg) body)."
+ `(progn ,@(mapcar (lambda (pair)
+ `(define-key ,mode-map (kbd ,(car pair))
+ (lambda () (interactive) (,argfunc ,(cdr pair)) ,@body)))
+ (eval binds))))
+
+(defvar notmuch-hello-tree-searches '(("u" . "tag:unread")
+ ("i" . "tag:inbox")
+ ("*" . "*"))
+ "List of (key . query) pairs to bind in notmuch-hello.")
+
+(make-binds notmuch-hello-mode-map
+ notmuch-hello-tree-searches
+ notmuch-search)
diff --git a/.emacs.d/rul-init.d/projectile.el b/.emacs.d/rul-init.d/projectile.el
new file mode 100644
index 0000000..ed95775
--- /dev/null
+++ b/.emacs.d/rul-init.d/projectile.el
@@ -0,0 +1,8 @@
+;; Debian packages: elpa-projectile
+
+(use-package projectile
+ :hook
+ (after-init . projectile-global-mode)
+ :config
+ (setq projectile-completion-system 'ivy)
+)
diff --git a/.emacs.d/rul-init.d/python.el b/.emacs.d/rul-init.d/python.el
new file mode 100644
index 0000000..3186c72
--- /dev/null
+++ b/.emacs.d/rul-init.d/python.el
@@ -0,0 +1 @@
+(add-hook 'python-mode-hook 'py-autopep8-enable-on-save)
diff --git a/.emacs.d/rul-init.d/sml.el b/.emacs.d/rul-init.d/sml.el
new file mode 100644
index 0000000..247d9b2
--- /dev/null
+++ b/.emacs.d/rul-init.d/sml.el
@@ -0,0 +1,7 @@
+;; Debian packages: elpa-smart-mode-line elpa-smart-mode-line-powerline-theme
+
+(use-package smart-mode-line
+ :ensure t
+ :config
+ (setq sml/theme 'respectful)
+ (sml/setup))
diff --git a/.emacs.d/rul-init.d/staging.el b/.emacs.d/rul-init.d/staging.el
new file mode 100644
index 0000000..7134fc3
--- /dev/null
+++ b/.emacs.d/rul-init.d/staging.el
@@ -0,0 +1,158 @@
+;; Debian packages: elpa-consult elpa-orderless elpa-vertico elpa-marginalia
+
+;; Example configuration for Consult
+(use-package consult
+ ;; Replace bindings. Lazily loaded due by `use-package'.
+ :bind (;; C-c bindings in `mode-specific-map'
+ ("C-c M-x" . consult-mode-command)
+ ("C-c h" . consult-history)
+ ("C-c k" . consult-kmacro)
+ ("C-c m" . consult-man)
+ ("C-c i" . consult-info)
+ ([remap Info-search] . consult-info)
+ ;; C-x bindings in `ctl-x-map'
+ ("C-x M-:" . consult-complex-command) ;; orig. repeat-complex-command
+ ("C-x b" . consult-buffer) ;; orig. switch-to-buffer
+ ("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window
+ ("C-x 5 b" . consult-buffer-other-frame) ;; orig. switch-to-buffer-other-frame
+ ("C-x r b" . consult-bookmark) ;; orig. bookmark-jump
+ ("C-x p b" . consult-project-buffer) ;; orig. project-switch-to-buffer
+ ;; Custom M-# bindings for fast register access
+ ("M-#" . consult-register-load)
+ ("M-'" . consult-register-store) ;; orig. abbrev-prefix-mark (unrelated)
+ ("C-M-#" . consult-register)
+ ;; Other custom bindings
+ ("M-y" . consult-yank-pop) ;; orig. yank-pop
+ ;; M-g bindings in `goto-map'
+ ("M-g e" . consult-compile-error)
+ ("M-g f" . consult-flymake) ;; Alternative: consult-flycheck
+ ("M-g g" . consult-goto-line) ;; orig. goto-line
+ ("M-g M-g" . consult-goto-line) ;; orig. goto-line
+ ("M-g o" . consult-outline) ;; Alternative: consult-org-heading
+ ("M-g m" . consult-mark)
+ ("M-g k" . consult-global-mark)
+ ("M-g i" . consult-imenu)
+ ("M-g I" . consult-imenu-multi)
+ ;; M-s bindings in `search-map'
+ ("M-s d" . consult-find)
+ ("M-s D" . consult-locate)
+ ("M-s g" . consult-grep)
+ ("M-s G" . consult-git-grep)
+ ("M-s r" . consult-ripgrep)
+ ("M-s l" . consult-line)
+ ("M-s L" . consult-line-multi)
+ ("M-s k" . consult-keep-lines)
+ ("M-s u" . consult-focus-lines)
+ ;; Isearch integration
+ ("M-s e" . consult-isearch-history)
+ :map isearch-mode-map
+ ("M-e" . consult-isearch-history) ;; orig. isearch-edit-string
+ ("M-s e" . consult-isearch-history) ;; orig. isearch-edit-string
+ ("M-s l" . consult-line) ;; needed by consult-line to detect isearch
+ ("M-s L" . consult-line-multi) ;; needed by consult-line to detect isearch
+ ;; Minibuffer history
+ :map minibuffer-local-map
+ ("M-s" . consult-history) ;; orig. next-matching-history-element
+ ("M-r" . consult-history)) ;; orig. previous-matching-history-element
+
+ ;; Enable automatic preview at point in the *Completions* buffer. This is
+ ;; relevant when you use the default completion UI.
+ :hook (completion-list-mode . consult-preview-at-point-mode)
+
+ ;; The :init configuration is always executed (Not lazy)
+ :init
+
+ ;; Optionally configure the register formatting. This improves the register
+ ;; preview for `consult-register', `consult-register-load',
+ ;; `consult-register-store' and the Emacs built-ins.
+ (setq register-preview-delay 0.5
+ register-preview-function #'consult-register-format)
+
+ ;; Optionally tweak the register preview window.
+ ;; This adds thin lines, sorting and hides the mode line of the window.
+ (advice-add #'register-preview :override #'consult-register-window)
+
+ ;; Use Consult to select xref locations with preview
+ (setq xref-show-xrefs-function #'consult-xref
+ xref-show-definitions-function #'consult-xref)
+
+ ;; Configure other variables and modes in the :config section,
+ ;; after lazily loading the package.
+ :config
+
+ ;; Optionally configure preview. The default value
+ ;; is 'any, such that any key triggers the preview.
+ ;; (setq consult-preview-key 'any)
+ ;; (setq consult-preview-key "M-.")
+ ;; (setq consult-preview-key '("S-<down>" "S-<up>"))
+ ;; For some commands and buffer sources it is useful to configure the
+ ;; :preview-key on a per-command basis using the `consult-customize' macro.
+ (consult-customize
+ consult-theme :preview-key '(:debounce 0.2 any)
+ consult-ripgrep consult-git-grep consult-grep
+ consult-bookmark consult-recent-file consult-xref
+ consult--source-bookmark consult--source-file-register
+ consult--source-recent-file consult--source-project-recent-file
+ ;; :preview-key "M-."
+ :preview-key '(:debounce 0.4 any))
+
+ ;; Optionally configure the narrowing key.
+ ;; Both < and C-+ work reasonably well.
+ (setq consult-narrow-key "<") ;; "C-+"
+
+ ;; Optionally make narrowing help available in the minibuffer.
+ ;; You may want to use `embark-prefix-help-command' or which-key instead.
+ ;; (define-key consult-narrow-map (vconcat consult-narrow-key "?") #'consult-narrow-help)
+
+ ;; By default `consult-project-function' uses `project-root' from project.el.
+ ;; Optionally configure a different project root function.
+ ;;;; 1. project.el (the default)
+ ;; (setq consult-project-function #'consult--default-project--function)
+ ;;;; 2. vc.el (vc-root-dir)
+ ;; (setq consult-project-function (lambda (_) (vc-root-dir)))
+ ;;;; 3. locate-dominating-file
+ ;; (setq consult-project-function (lambda (_) (locate-dominating-file "." ".git")))
+ ;;;; 4. projectile.el (projectile-project-root)
+ ;; (autoload 'projectile-project-root "projectile")
+ ;; (setq consult-project-function (lambda (_) (projectile-project-root)))
+ ;;;; 5. No project support
+ ;; (setq consult-project-function nil)
+)
+
+;; Enable vertico
+(use-package vertico
+ :init
+ (vertico-mode)
+
+ ;; Different scroll margin
+ ;; (setq vertico-scroll-margin 0)
+
+ ;; Show more candidates
+ ;; (setq vertico-count 20)
+
+ ;; Grow and shrink the Vertico minibuffer
+ ;; (setq vertico-resize t)
+
+ ;; Optionally enable cycling for `vertico-next' and `vertico-previous'.
+ ;; (setq vertico-cycle t)
+ )
+
+;; Enable rich annotations using the Marginalia package
+(use-package marginalia
+ ;; Bind `marginalia-cycle' locally in the minibuffer. To make the binding
+ ;; available in the *Completions* buffer, add it to the
+ ;; `completion-list-mode-map'.
+ :bind (:map minibuffer-local-map
+ ("M-A" . marginalia-cycle))
+
+ ;; The :init section is always executed.
+ :init
+
+ ;; Marginalia must be actived in the :init section of use-package such that
+ ;; the mode gets enabled right away. Note that this forces loading the
+ ;; package.
+ (marginalia-mode))
+
+(setq completion-styles '(flex basic)
+ completion-category-defaults nil
+ completion-category-overrides nil)
diff --git a/.emacs.d/rul-init.d/tabbar.el b/.emacs.d/rul-init.d/tabbar.el
new file mode 100644
index 0000000..a492e85
--- /dev/null
+++ b/.emacs.d/rul-init.d/tabbar.el
@@ -0,0 +1,25 @@
+(global-set-key (kbd "C-<next>") 'tab-bar-switch-to-next-tab)
+(global-set-key (kbd "C-<prior>") 'tab-bar-switch-to-prev-tab)
+
+(setq tab-bar-show t)
+
+(defun my/project-create-tab ()
+ (interactive)
+ (tab-bar-new-tab)
+ (magit-status))
+
+(setq project-switch-commands #'my/project-create-tab)
+
+(defun my/switch-to-tab-buffer ()
+ (interactive)
+ (if (project-current)
+ (call-interactively #'projectile-switch-to-buffer)
+ (call-interactively #'switch-to-buffer)))
+
+(global-set-key (kbd "C-x b") #'my/switch-to-tab-buffer)
+
+;; Turn on tab bar mode after startup
+(tab-bar-mode 1)
+
+;; Save the desktop session
+(desktop-save-mode 1)
diff --git a/.emacs.d/rul-init.d/themes.el b/.emacs.d/rul-init.d/themes.el
new file mode 100644
index 0000000..c94d4a1
--- /dev/null
+++ b/.emacs.d/rul-init.d/themes.el
@@ -0,0 +1,47 @@
+(use-package ef-themes :ensure t)
+
+(setq
+ modus-themes-mode-line '(accented borderless padded)
+ modus-themes-region '(bg-only)
+ modus-themes-bold-constructs t
+ modus-themes-italic-constructs t
+ modus-themes-paren-match '(bold intense)
+ modus-themes-headings (quote ((1 . (rainbow variable-pitch 1.3))
+ (2 . (rainbow 1.1))
+ (t . (rainbow))))
+ modus-themes-org-blocks 'tinted
+ )
+
+(use-package dbus)
+(defun mf/set-theme-from-dbus-value (value)
+ "Set the appropiate theme according to the color-scheme setting value."
+ (message "value is %s" value)
+ (if (equal value '1)
+ (progn (message "Switch to dark theme")
+ (modus-themes-select 'modus-vivendi-tinted))
+ (progn (message "Switch to light theme")
+ (modus-themes-select 'modus-operandi-tinted))))
+
+(defun mf/color-scheme-changed (path var value)
+ "DBus handler to detect when the color-scheme has changed."
+ (when (and (string-equal path "org.freedesktop.appearance")
+ (string-equal var "color-scheme"))
+ (mf/set-theme-from-dbus-value (car value))
+ ))
+
+;; Register for future changes
+(dbus-register-signal
+ :session "org.freedesktop.portal.Desktop"
+ "/org/freedesktop/portal/desktop" "org.freedesktop.portal.Settings"
+ "SettingChanged"
+ #'mf/color-scheme-changed)
+
+;; Request the current color-scheme
+(dbus-call-method-asynchronously
+ :session "org.freedesktop.portal.Desktop"
+ "/org/freedesktop/portal/desktop" "org.freedesktop.portal.Settings"
+ "Read"
+ (lambda (value) (mf/set-theme-from-dbus-value (caar value)))
+ "org.freedesktop.appearance"
+ "color-scheme"
+ )
diff --git a/.emacs.d/rul-init.d/vterm.el b/.emacs.d/rul-init.d/vterm.el
new file mode 100644
index 0000000..54abbbf
--- /dev/null
+++ b/.emacs.d/rul-init.d/vterm.el
@@ -0,0 +1,6 @@
+(use-package multi-vterm
+:ensure t
+:config
+(setq
+ vterm-max-scrollback 100000
+))
diff --git a/.emacs.d/rul-init.d/which-key.el b/.emacs.d/rul-init.d/which-key.el
new file mode 100644
index 0000000..1d8fd8d
--- /dev/null
+++ b/.emacs.d/rul-init.d/which-key.el
@@ -0,0 +1,5 @@
+(use-package which-key
+ :ensure t
+ :config
+ (which-key-mode)
+)
diff --git a/.emacs.d/rul-init.d/writeroom.el b/.emacs.d/rul-init.d/writeroom.el
new file mode 100644
index 0000000..50780cc
--- /dev/null
+++ b/.emacs.d/rul-init.d/writeroom.el
@@ -0,0 +1,34 @@
+(use-package writeroom-mode
+ :defer t
+ :config
+ (setq writeroom-width 140
+ writeroom-mode-line nil
+ writeroom-global-effects '(writeroom-set-bottom-divider-width
+ writeroom-set-internal-border-width
+ (lambda (arg)
+ (let ((langs '("python"
+ "emacs-lisp"
+ "common-lisp"
+ "js"
+ "ruby")))
+ (cond
+ ((= arg 1)
+ (progn
+ (setq org-src-block-faces
+ (mapcar (lambda (lang) (list lang '(:family "Source Code Pro" :height 0.8))) langs))
+ (normal-mode)
+ (variable-pitch-mode)))
+ ((= arg -1)
+ (progn
+ (setq org-src-block-faces
+ (mapcar (lambda (lang) (list lang '(:family "Source Code Pro" :height 1.0))) langs))
+ (normal-mode)
+ (variable-pitch-mode)
+(variable-pitch-mode)))))))))
+
+(use-package olivetti
+ :defer t
+ :config
+ (setq
+ olivetti-body-width 86
+ ))
diff --git a/.emacs.d/rul-lisp/config/rul-config-elfeed.el b/.emacs.d/rul-lisp/config/rul-config-elfeed.el
new file mode 100644
index 0000000..026c325
--- /dev/null
+++ b/.emacs.d/rul-lisp/config/rul-config-elfeed.el
@@ -0,0 +1,2 @@
+(setq elfeed-feeds '("https://planet.debian.org/rss10.xml"))
+(provide 'rul-config-elfeed)
diff --git a/.emacs.d/rul-lisp/config/rul-config-mail.el b/.emacs.d/rul-lisp/config/rul-config-mail.el
new file mode 100644
index 0000000..240f8be
--- /dev/null
+++ b/.emacs.d/rul-lisp/config/rul-config-mail.el
@@ -0,0 +1 @@
+(provide 'rul-config-mail)
diff --git a/.emacs.d/rul-lisp/config/rul-config-org.el b/.emacs.d/rul-lisp/config/rul-config-org.el
new file mode 100644
index 0000000..bf538dc
--- /dev/null
+++ b/.emacs.d/rul-lisp/config/rul-config-org.el
@@ -0,0 +1,22 @@
+(setq
+ org-agenda-files '("~/org/")
+ org-agenda-custom-commands
+ '(("x" agenda)
+ ("y" agenda*)
+ ("w" todo "WAITING")
+ ("W" todo-tree "WAITING")
+ )
+ org-journal-file-type 'yearly
+ org-journal-dir "~/org/journal/"
+ org-journal-file-format "%Y.org"
+ org-journal-time-prefix "* "
+ org-journal-time-format ""
+ org-refile-path "~/refile.org"
+ org-roam-directory "~/org/roam/"
+
+ org-agenda-private-local-path "/tmp/example.ics"
+ org-agenda-private-remote-path "/sshx:user@host:example.ics"
+ )
+
+(provide 'rul-config-org)
+
diff --git a/.emacs.d/rul-lisp/packages/rul-dart.el b/.emacs.d/rul-lisp/packages/rul-dart.el
new file mode 100644
index 0000000..36bfd47
--- /dev/null
+++ b/.emacs.d/rul-lisp/packages/rul-dart.el
@@ -0,0 +1,7 @@
+(setq dart-server-format-on-save t)
+(add-hook 'dart-mode-hook 'lsp)
+
+(setq gc-cons-threshold (* 100 1024 1024)
+ read-process-output-max (* 1024 1024))
+
+(provide 'rul-dart)
diff --git a/.emacs.d/rul-lisp/packages/rul-elfeed.el b/.emacs.d/rul-lisp/packages/rul-elfeed.el
new file mode 100644
index 0000000..34713db
--- /dev/null
+++ b/.emacs.d/rul-lisp/packages/rul-elfeed.el
@@ -0,0 +1,5 @@
+(use-package elfeed
+ :config
+ (require 'rul-config-elfeed))
+
+(provide 'rul-elfeed)
diff --git a/.emacs.d/rul-lisp/packages/rul-org-agenda.el b/.emacs.d/rul-lisp/packages/rul-org-agenda.el
new file mode 100644
index 0000000..7b6c4b4
--- /dev/null
+++ b/.emacs.d/rul-lisp/packages/rul-org-agenda.el
@@ -0,0 +1,417 @@
+(require 'org)
+
+(global-set-key (kbd "<f12>") #'org-agenda)
+(global-set-key (kbd "C-c a") #'org-agenda)
+
+(defun bh/is-project-p ()
+ "Any task with a todo keyword subtask"
+ (save-restriction
+ (widen)
+ (let ((has-subtask)
+ (subtree-end (save-excursion (org-end-of-subtree t)))
+ (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1)))
+ (save-excursion
+ (forward-line 1)
+ (while (and (not has-subtask)
+ (< (point) subtree-end)
+ (re-search-forward "^\*+ " subtree-end t))
+ (when (member (org-get-todo-state) org-todo-keywords-1)
+ (setq has-subtask t))))
+ (and is-a-task has-subtask))))
+
+(defun bh/is-project-subtree-p ()
+ "Any task with a todo keyword that is in a project subtree.
+Callers of this function already widen the buffer view."
+ (let ((task (save-excursion (org-back-to-heading 'invisible-ok)
+ (point))))
+ (save-excursion
+ (bh/find-project-task)
+ (if (equal (point) task)
+ nil
+ t))))
+
+(defun bh/is-task-p ()
+ "Any task with a todo keyword and no subtask"
+ (save-restriction
+ (widen)
+ (let ((has-subtask)
+ (subtree-end (save-excursion (org-end-of-subtree t)))
+ (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1)))
+ (save-excursion
+ (forward-line 1)
+ (while (and (not has-subtask)
+ (< (point) subtree-end)
+ (re-search-forward "^\*+ " subtree-end t))
+ (when (member (org-get-todo-state) org-todo-keywords-1)
+ (setq has-subtask t))))
+ (and is-a-task (not has-subtask)))))
+
+(defun bh/is-subproject-p ()
+ "Any task which is a subtask of another project"
+ (let ((is-subproject)
+ (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1)))
+ (save-excursion
+ (while (and (not is-subproject) (org-up-heading-safe))
+ (when (member (nth 2 (org-heading-components)) org-todo-keywords-1)
+ (setq is-subproject t))))
+ (and is-a-task is-subproject)))
+
+(defun bh/list-sublevels-for-projects-indented ()
+ "Set org-tags-match-list-sublevels so when restricted to a subtree we list all subtasks.
+ This is normally used by skipping functions where this variable is already local to the agenda."
+ (if (marker-buffer org-agenda-restrict-begin)
+ (setq org-tags-match-list-sublevels 'indented)
+ (setq org-tags-match-list-sublevels nil))
+ nil)
+
+(defun bh/list-sublevels-for-projects ()
+ "Set org-tags-match-list-sublevels so when restricted to a subtree we list all subtasks.
+ This is normally used by skipping functions where this variable is already local to the agenda."
+ (if (marker-buffer org-agenda-restrict-begin)
+ (setq org-tags-match-list-sublevels t)
+ (setq org-tags-match-list-sublevels nil))
+ nil)
+
+(defvar bh/hide-scheduled-and-waiting-next-tasks t)
+
+(defun bh/toggle-next-task-display ()
+ (interactive)
+ (setq bh/hide-scheduled-and-waiting-next-tasks (not bh/hide-scheduled-and-waiting-next-tasks))
+ (when (equal major-mode 'org-agenda-mode)
+ (org-agenda-redo))
+ (message "%s WAITING and SCHEDULED NEXT Tasks" (if bh/hide-scheduled-and-waiting-next-tasks "Hide" "Show")))
+
+(defun bh/skip-stuck-projects ()
+ "Skip trees that are not stuck projects"
+ (save-restriction
+ (widen)
+ (let ((next-headline (save-excursion (or (outline-next-heading) (point-max)))))
+ (if (bh/is-project-p)
+ (let* ((subtree-end (save-excursion (org-end-of-subtree t)))
+ (has-next ))
+ (save-excursion
+ (forward-line 1)
+ (while (and (not has-next) (< (point) subtree-end) (re-search-forward "^\\*+ NEXT " subtree-end t))
+ (unless (member "WAITING" (org-get-tags-at))
+ (setq has-next t))))
+ (if has-next
+ nil
+ next-headline)) ; a stuck project, has subtasks but no next task
+ nil))))
+
+(defun bh/skip-non-stuck-projects ()
+ "Skip trees that are not stuck projects"
+ ;; (bh/list-sublevels-for-projects-indented)
+ (save-restriction
+ (widen)
+ (let ((next-headline (save-excursion (or (outline-next-heading) (point-max)))))
+ (if (bh/is-project-p)
+ (let* ((subtree-end (save-excursion (org-end-of-subtree t)))
+ (has-next ))
+ (save-excursion
+ (forward-line 1)
+ (while (and (not has-next) (< (point) subtree-end) (re-search-forward "^\\*+ NEXT " subtree-end t))
+ (unless (member "WAITING" (org-get-tags-at))
+ (setq has-next t))))
+ (if has-next
+ next-headline
+ nil)) ; a stuck project, has subtasks but no next task
+ next-headline))))
+
+(defun bh/skip-non-projects ()
+ "Skip trees that are not projects"
+ ;; (bh/list-sublevels-for-projects-indented)
+ (if (save-excursion (bh/skip-non-stuck-projects))
+ (save-restriction
+ (widen)
+ (let ((subtree-end (save-excursion (org-end-of-subtree t))))
+ (cond
+ ((bh/is-project-p)
+ nil)
+ ((and (bh/is-project-subtree-p) (not (bh/is-task-p)))
+ nil)
+ (t
+ subtree-end))))
+ (save-excursion (org-end-of-subtree t))))
+
+(defun bh/skip-non-tasks ()
+ "Show non-project tasks.
+Skip project and sub-project tasks, habits, and project related tasks."
+ (save-restriction
+ (widen)
+ (let ((next-headline (save-excursion (or (outline-next-heading) (point-max)))))
+ (cond
+ ((bh/is-task-p)
+ nil)
+ (t
+ next-headline)))))
+
+(defun bh/skip-project-trees-and-habits ()
+ "Skip trees that are projects"
+ (save-restriction
+ (widen)
+ (let ((subtree-end (save-excursion (org-end-of-subtree t))))
+ (cond
+ ((bh/is-project-p)
+ subtree-end)
+ ((org-is-habit-p)
+ subtree-end)
+ (t
+ nil)))))
+
+(defun bh/skip-projects-and-habits-and-single-tasks ()
+ "Skip trees that are projects, tasks that are habits, single non-project tasks"
+ (save-restriction
+ (widen)
+ (let ((next-headline (save-excursion (or (outline-next-heading) (point-max)))))
+ (cond
+ ((org-is-habit-p)
+ next-headline)
+ ((and bh/hide-scheduled-and-waiting-next-tasks
+ (member "WAITING" (org-get-tags-at)))
+ next-headline)
+ ((bh/is-project-p)
+ next-headline)
+ ((and (bh/is-task-p) (not (bh/is-project-subtree-p)))
+ next-headline)
+ (t
+ nil)))))
+
+(defun bh/skip-project-tasks-maybe ()
+ "Show tasks related to the current restriction.
+When restricted to a project, skip project and sub project tasks, habits, NEXT tasks, and loose tasks.
+When not restricted, skip project and sub-project tasks, habits, and project related tasks."
+ (save-restriction
+ (widen)
+ (let* ((subtree-end (save-excursion (org-end-of-subtree t)))
+ (next-headline (save-excursion (or (outline-next-heading) (point-max))))
+ (limit-to-project (marker-buffer org-agenda-restrict-begin)))
+ (cond
+ ((bh/is-project-p)
+ next-headline)
+ ((org-is-habit-p)
+ subtree-end)
+ ((and (not limit-to-project)
+ (bh/is-project-subtree-p))
+ subtree-end)
+ ((and limit-to-project
+ (bh/is-project-subtree-p)
+ (member (org-get-todo-state) (list "NEXT")))
+ subtree-end)
+ (t
+ nil)))))
+
+(defun bh/skip-project-tasks ()
+ "Show non-project tasks.
+Skip project and sub-project tasks, habits, and project related tasks."
+ (save-restriction
+ (widen)
+ (let* ((subtree-end (save-excursion (org-end-of-subtree t))))
+ (cond
+ ((bh/is-project-p)
+ subtree-end)
+ ((org-is-habit-p)
+ subtree-end)
+ ((bh/is-project-subtree-p)
+ subtree-end)
+ (t
+ nil)))))
+
+(defun bh/skip-non-project-tasks ()
+ "Show project tasks.
+Skip project and sub-project tasks, habits, and loose non-project tasks."
+ (save-restriction
+ (widen)
+ (let* ((subtree-end (save-excursion (org-end-of-subtree t)))
+ (next-headline (save-excursion (or (outline-next-heading) (point-max)))))
+ (cond
+ ((bh/is-project-p)
+ next-headline)
+ ((org-is-habit-p)
+ subtree-end)
+ ((and (bh/is-project-subtree-p)
+ (member (org-get-todo-state) (list "NEXT")))
+ subtree-end)
+ ((not (bh/is-project-subtree-p))
+ subtree-end)
+ (t
+ nil)))))
+
+(defun bh/skip-projects-and-habits ()
+ "Skip trees that are projects and tasks that are habits"
+ (save-restriction
+ (widen)
+ (let ((subtree-end (save-excursion (org-end-of-subtree t))))
+ (cond
+ ((bh/is-project-p)
+ subtree-end)
+ ((org-is-habit-p)
+ subtree-end)
+ (t
+ nil)))))
+
+(defun bh/skip-non-subprojects ()
+ "Skip trees that are not projects"
+ (let ((next-headline (save-excursion (outline-next-heading))))
+ (if (bh/is-subproject-p)
+ nil
+ next-headline)))
+
+;; CLOCKING ;;
+;; Resume clocking task when emacs is restarted
+(org-clock-persistence-insinuate)
+;;
+;; Show lot of clocking history so it's easy to pick items off the C-F11 list
+(setq org-clock-history-length 23)
+;; Resume clocking task on clock-in if the clock is open
+(setq org-clock-in-resume t)
+;; Change tasks to NEXT when clocking in
+(setq org-clock-in-switch-to-state 'bh/clock-in-to-next)
+;; Separate drawers for clocking and logs
+(setq org-drawers (quote ("PROPERTIES" "LOGBOOK")))
+;; Save clock data and state changes and notes in the LOGBOOK drawer
+(setq org-clock-into-drawer t)
+;; Sometimes I change tasks I'm clocking quickly - this removes clocked tasks with 0:00 duration
+(setq org-clock-out-remove-zero-time-clocks t)
+;; Clock out when moving task to a done state
+(setq org-clock-out-when-done t)
+;; Save the running clock and all clock history when exiting Emacs, load it on startup
+(setq org-clock-persist t)
+;; Do not prompt to resume an active clock
+(setq org-clock-persist-query-resume nil)
+;; Enable auto clock resolution for finding open clocks
+(setq org-clock-auto-clock-resolution (quote when-no-clock-is-running))
+;; Include current clocking task in clock reports
+(setq org-clock-report-include-clocking-task t)
+
+
+(setq bh/keep-clock-running nil)
+
+(defun bh/clock-in-to-next (kw)
+ "Switch a task from TODO to NEXT when clocking in.
+Skips capture tasks, projects, and subprojects.
+Switch projects and subprojects from NEXT back to TODO"
+ (when (not (and (boundp 'org-capture-mode) org-capture-mode))
+ (cond
+ ((and (member (org-get-todo-state) (list "TODO"))
+ (bh/is-task-p))
+ "NEXT")
+ ((and (member (org-get-todo-state) (list "NEXT"))
+ (bh/is-project-p))
+ "TODO"))))
+
+(defun bh/find-project-task ()
+ "Move point to the parent (project) task if any"
+ (save-restriction
+ (widen)
+ (let ((parent-task (save-excursion (org-back-to-heading 'invisible-ok) (point))))
+ (while (org-up-heading-safe)
+ (when (member (nth 2 (org-heading-components)) org-todo-keywords-1)
+ (setq parent-task (point))))
+ (goto-char parent-task)
+ parent-task)))
+
+(defun bh/punch-in (arg)
+ "Start continuous clocking and set the default task to the
+selected task. If no task is selected set the Organization task
+as the default task."
+ (interactive "p")
+ (setq bh/keep-clock-running t)
+ (if (equal major-mode 'org-agenda-mode)
+ ;;
+ ;; We're in the agenda
+ ;;
+ (let* ((marker (org-get-at-bol 'org-hd-marker))
+ (tags (org-with-point-at marker (org-get-tags-at))))
+ (if (and (eq arg 4) tags)
+ (org-agenda-clock-in '(16))
+ (bh/clock-in-organization-task-as-default)))
+ ;;
+ ;; We are not in the agenda
+ ;;
+ (save-restriction
+ (widen)
+ ; Find the tags on the current task
+ (if (and (equal major-mode 'org-mode) (not (org-before-first-heading-p)) (eq arg 4))
+ (org-clock-in '(16))
+ (bh/clock-in-organization-task-as-default)))))
+
+(defun bh/punch-out ()
+ (interactive)
+ (setq bh/keep-clock-running nil)
+ (when (org-clock-is-active)
+ (org-clock-out))
+ (org-agenda-remove-restriction-lock))
+
+(defun bh/clock-in-default-task ()
+ (save-excursion
+ (org-with-point-at org-clock-default-task
+ (org-clock-in))))
+
+(defun bh/clock-in-parent-task ()
+ "Move point to the parent (project) task if any and clock in"
+ (let ((parent-task))
+ (save-excursion
+ (save-restriction
+ (widen)
+ (while (and (not parent-task) (org-up-heading-safe))
+ (when (member (nth 2 (org-heading-components)) org-todo-keywords-1)
+ (setq parent-task (point))))
+ (if parent-task
+ (org-with-point-at parent-task
+ (org-clock-in))
+ (when bh/keep-clock-running
+ (bh/clock-in-default-task)))))))
+
+(defvar bh/organization-task-id "eb155a82-92b2-4f25-a3c6-0304591af2f9")
+
+;; https://stackoverflow.com/a/10091330
+(defun zin/org-agenda-skip-tag (tag &optional others)
+ "Skip all entries that correspond to TAG.
+
+If OTHERS is true, skip all entries that do not correspond to TAG."
+ (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))
+ (current-headline (or (and (org-at-heading-p)
+ (point))
+ (save-excursion (org-back-to-heading)))))
+ (if others
+ (if (not (member tag (org-get-tags-at current-headline)))
+ next-headline
+ nil)
+ (if (member tag (org-get-tags-at current-headline))
+ next-headline
+ nil))))
+
+(defun bh/clock-in-organization-task-as-default ()
+ (interactive)
+ (org-with-point-at (org-id-find bh/organization-task-id 'marker)
+ (org-clock-in '(16))))
+
+(defun bh/clock-out-maybe ()
+ (when (and bh/keep-clock-running
+ (not org-clock-clocking-in)
+ (marker-buffer org-clock-default-task)
+ (not org-clock-resolving-clocks-due-to-idleness))
+ (bh/clock-in-parent-task)))
+
+(add-hook 'org-clock-out-hook 'bh/clock-out-maybe 'append)
+
+;; AGENDA VIEW ;;
+
+;; Do not dim blocked tasks
+(setq org-agenda-compact-blocks nil)
+(setq org-agenda-dim-blocked-tasks nil)
+(setq org-agenda-block-separator 61)
+
+;; Agenda log mode items to display (closed and state changes by default)
+(setq org-agenda-log-mode-items (quote (closed state)))
+
+; For tag searches ignore tasks with scheduled and deadline dates
+(setq org-agenda-tags-todo-honor-ignore-options t)
+
+(setq org-icalendar-include-body nil)
+(setq org-icalendar-include-bbdb-anniversaries t)
+(setq org-icalendar-include-todo t)
+(setq org-icalendar-use-scheduled '(todo-start event-if-not-todo event-if-todo-not-done))
+
+(provide 'rul-org-agenda)
diff --git a/.emacs.d/rul-lisp/packages/rul-org-journal.el b/.emacs.d/rul-lisp/packages/rul-org-journal.el
new file mode 100644
index 0000000..9d30e00
--- /dev/null
+++ b/.emacs.d/rul-lisp/packages/rul-org-journal.el
@@ -0,0 +1,11 @@
+(use-package org-journal
+ :ensure t
+ :init
+ ;; Change default prefix key; needs to be set before loading org-journal
+ (setq org-journal-prefix-key "C-c j ")
+ (setq org-journal-enable-agenda-integration t)
+ :config
+ (require 'rul-config-org)
+ (setq org-journal-date-format "%A, %d %B %Y"))
+
+(provide 'rul-org-journal)
diff --git a/.emacs.d/rul-lisp/packages/rul-org-notify.el b/.emacs.d/rul-lisp/packages/rul-org-notify.el
new file mode 100644
index 0000000..50c35a0
--- /dev/null
+++ b/.emacs.d/rul-lisp/packages/rul-org-notify.el
@@ -0,0 +1,9 @@
+(use-package org-notify
+ :ensure t
+ :config
+ (org-notify-start)
+ (org-notify-add 'default
+ '(:time "-1s" :period "20s" :duration 10
+ :actions (-message -ding))
+ '(:time "1d" :actions -notify/window
+ :duration 60)))
diff --git a/.emacs.d/rul-lisp/packages/rul-org-roam.el b/.emacs.d/rul-lisp/packages/rul-org-roam.el
new file mode 100644
index 0000000..f30e86e
--- /dev/null
+++ b/.emacs.d/rul-lisp/packages/rul-org-roam.el
@@ -0,0 +1,24 @@
+(use-package org-roam
+ :ensure t
+ :after rul-org
+ :init
+ (setq org-roam-v2-ack t)
+ :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))
+ :config
+ (require 'rul-config-org)
+ (org-roam-setup)
+ (add-to-list 'display-buffer-alist
+ '("\\*org-roam\\*"
+ (display-buffer-in-direction)
+ (direction . right)
+ (window-width . 0.33)
+ (window-height . fit-window-to-buffer)))
+ (setq org-roam-mode-section-functions
+ (list #'org-roam-backlinks-section
+ #'org-roam-reflinks-section
+ #'org-roam-unlinked-references-section))
+ )
+
+(provide 'rul-org-roam)
diff --git a/.emacs.d/rul-lisp/packages/rul-org.el b/.emacs.d/rul-lisp/packages/rul-org.el
new file mode 100644
index 0000000..0727239
--- /dev/null
+++ b/.emacs.d/rul-lisp/packages/rul-org.el
@@ -0,0 +1,156 @@
+;; Debian packages: elpa-org elpa-org-bullets
+;; Elpa packages: org-modern
+(require 'org)
+(require 'org-capture)
+(require 'org-protocol)
+(require 'org-habit)
+(require 'org-bullets)
+
+(require 'org-modern)
+
+(require 'rul-config-org)
+
+(require 'rul-org-agenda)
+(require 'rul-org-journal)
+(require 'rul-org-roam)
+
+(setq org-cycle-separator-lines 0)
+(setq org-startup-indented t)
+(setq org-hide-leading-stars nil)
+
+(add-hook 'org-mode-hook 'turn-off-auto-fill)
+(add-hook 'org-mode-hook 'visual-line-mode)
+
+(setq org-startup-indented t
+ org-bullets-bullet-list '(" ") ;; no bullets, needs org-bullets package
+ org-pretty-entities nil
+ org-hide-emphasis-markers t
+ ;; show actually italicized text instead of /italicized text/
+ org-fontify-whole-heading-line t
+ org-fontify-done-headline t
+ org-fontify-quote-and-verse-blocks t)
+
+;; ORG BINDINGS ;;
+(global-set-key (kbd "C-c l") #'org-store-link)
+(global-set-key (kbd "C-c c") #'org-capture)
+(global-set-key (kbd "C-c s") #'org-schedule)
+
+;; ORG STATES ;;
+(setq org-todo-keywords
+ (quote ((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d)")
+ (sequence "WAITING(w@/!)" "HOLD(h@/!)" "|" "CANCELLED(c@/!)" "PHONE" "MEETING"))))
+
+(setq org-use-fast-todo-selection t)
+
+(setq org-todo-state-tags-triggers
+ (quote (("CANCELLED" ("CANCELLED" . t))
+ ("WAITING" ("WAITING" . t))
+ ("HOLD" ("WAITING") ("HOLD" . t))
+ (done ("WAITING") ("HOLD"))
+ ("TODO" ("WAITING") ("CANCELLED") ("HOLD"))
+ ("NEXT" ("WAITING") ("CANCELLED") ("HOLD"))
+ ("DONE" ("WAITING") ("CANCELLED") ("HOLD")))))
+
+(setq org-enforce-todo-dependencies t)
+(setq org-log-done (quote time))
+(setq org-log-redeadline (quote time))
+(setq org-log-reschedule (quote time))
+
+;; CAPTURE ;;
+(setq org-default-notes-file org-refile-path)
+(setq org-capture-templates
+ (quote
+ (
+ ("w" "Todo" entry (file+headline org-refile-path "Tasks")
+ "* TODO "
+ :empty-lines 1)
+ ("m"
+ "Capture incoming email"
+ entry
+ (file+headline org-refile-path "Incoming")
+ "* TODO Re: %:description\n\n Source: %u, %a\n"
+ :empty-lines 1)
+ )))
+
+(add-hook 'org-capture-mode-hook 'delete-other-windows)
+(setq org-protocol-flag nil)
+
+(defadvice org-capture-finalize (after delete-frame-at-end activate)
+ "Delete frame at remember finalization"
+ (progn (if org-protocol-flag (delete-frame))
+ (setq org-protocol-flag nil)))
+
+(defadvice org-capture-kill (after delete-frame-at-end activate)
+ "Delete frame at remember abort"
+ (progn (if org-protocol-flag (delete-frame))
+ (setq org-protocol-flag nil)))
+
+(defadvice org-protocol-capture (before set-org-protocol-flag activate)
+ (setq org-protocol-flag t))
+
+
+;; REFILE ;;
+
+; Targets include this file and any file contributing to the agenda - up to 3 levels deep
+(setq org-refile-targets
+ '((nil :maxlevel . 3)
+ (org-agenda-files :maxlevel . 3)))
+
+; Targets complete directly with IDO
+(setq org-outline-path-complete-in-steps nil)
+
+; Allow refile to create parent tasks with confirmation
+(setq org-refile-allow-creating-parent-nodes (quote confirm))
+
+
+
+;; ORG REPORTS ;;
+; Set default column view headings: Task Effort Clock_Summary
+(setq org-columns-default-format "%80ITEM(Task) %10Effort(Effort){:} %10CLOCKSUM")
+
+(defun my-org-clocktable-indent-string (level)
+ (if (= level 1)
+ ""
+ (let ((str "^"))
+ (while (> level 2)
+ (setq level (1- level)
+ str (concat str "--")))
+ (concat str "-> "))))
+
+(advice-add 'org-clocktable-indent-string :override #'my-org-clocktable-indent-string)
+
+(setq org-clock-clocktable-default-properties '(:maxlevel 4 :scope file :formula %))
+
+; global Effort estimate values
+; global STYLE property values for completion
+(setq org-global-properties (quote (("Effort_ALL" . "0:15 0:30 0:45 1:00 2:00 3:00 4:00 5:00 6:00 0:00")
+ ("STYLE_ALL" . "habit"))))
+
+;; TAGS ;;
+; Tags with fast selection keys
+(setq org-tag-alist (quote ((:startgroup)
+ ("@errand" . ?e)
+ ("@office" . ?o)
+ ("@home" . ?H)
+ (:endgroup)
+ ("WAITING" . ?w)
+ ("HOLD" . ?h)
+ ("PERSONAL" . ?P)
+ ("WORK" . ?W)
+ ("ORG" . ?O)
+ ("NOTE" . ?n)
+ ("CANCELLED" . ?c)
+ ("FLAGGED" . ??))))
+
+(setq org-stuck-projects
+ '("+LEVEL=2+PROJECT/-MAYBE-DONE" ("NEXT") ("@shop")
+ "\\<IGNORE\\>"))
+
+; Allow setting single tags without the menu
+(setq org-fast-tag-selection-single-key (quote expert))
+
+;; org-modern
+(add-hook 'org-mode-hook 'org-modern-mode)
+(add-hook 'org-agenda-finalize-hook #'org-modern-agenda)
+
+(provide 'rul-org)
nihil fit ex nihilo