mirror of
https://github.com/SqrtMinusOne/dotfiles.git
synced 2025-12-10 19:23:03 +03:00
feat(emacs): some changes in org-mode
This commit is contained in:
parent
3f5967a5f6
commit
eb20f672eb
2 changed files with 505 additions and 500 deletions
351
.emacs.d/init.el
351
.emacs.d/init.el
|
|
@ -2172,6 +2172,13 @@ Returns (<buffer> . <workspace-index>) or nil."
|
|||
"p" 'langtool-goto-previous-error
|
||||
"l" 'langtool-correct-buffer)
|
||||
|
||||
(use-package reverso
|
||||
:straight (:host github :repo "SqrtMinusOne/reverso.el")
|
||||
:init
|
||||
(my-leader-def "ar" #'reverso)
|
||||
:config
|
||||
(setq reverso-languages '(russian english german)))
|
||||
|
||||
(use-package lispy
|
||||
:commands (lispy-mode)
|
||||
:straight t)
|
||||
|
|
@ -2239,6 +2246,7 @@ Returns (<buffer> . <workspace-index>) or nil."
|
|||
(use-package clips-mode
|
||||
:straight t
|
||||
:mode "\\.cl\\'"
|
||||
:disabled t
|
||||
:config
|
||||
(add-hook 'clips-mode 'lispy-mode))
|
||||
|
||||
|
|
@ -2434,6 +2442,31 @@ Returns (<buffer> . <workspace-index>) or nil."
|
|||
:config
|
||||
(add-hook 'fish-mode-hook #'smartparens-mode))
|
||||
|
||||
(setq my/sqlformatter-dialect-choice
|
||||
'("db2" "mariadb" "mysql" "n1ql" "plsql" "postgresql" "redshift" "spark" "sql" "tsql"))
|
||||
|
||||
(setq my/sqlformatter-dialect "postgresql")
|
||||
|
||||
(defun my/sqlformatter-set-dialect ()
|
||||
"Set dialect for sql-formatter"
|
||||
(interactive)
|
||||
(setq my/sqlformatter-dialect
|
||||
(completing-read "Dialect: " my/sqlformatter-dialect-choice)))
|
||||
|
||||
(reformatter-define sqlformat
|
||||
:program (executable-find "sql-formatter")
|
||||
:args `("-l" ,my/sqlformatter-dialect))
|
||||
|
||||
(my-leader-def
|
||||
:keymaps '(sql-mode-map)
|
||||
"rr" #'sqlformat-buffer)
|
||||
|
||||
(use-package sparql-mode
|
||||
:straight t)
|
||||
|
||||
(use-package graphql-mode
|
||||
:straight t)
|
||||
|
||||
(use-package x509-mode
|
||||
:straight t)
|
||||
|
||||
|
|
@ -2493,28 +2526,6 @@ Returns (<buffer> . <workspace-index>) or nil."
|
|||
|
||||
(my/set-smartparens-indent 'lua-mode)
|
||||
|
||||
(setq my/sqlformatter-dialect-choice
|
||||
'("db2" "mariadb" "mysql" "n1ql" "plsql" "postgresql" "redshift" "spark" "sql" "tsql"))
|
||||
|
||||
(setq my/sqlformatter-dialect "postgresql")
|
||||
|
||||
(defun my/sqlformatter-set-dialect ()
|
||||
"Set dialect for sql-formatter"
|
||||
(interactive)
|
||||
(setq my/sqlformatter-dialect
|
||||
(completing-read "Dialect: " my/sqlformatter-dialect-choice)))
|
||||
|
||||
(reformatter-define sqlformat
|
||||
:program (executable-find "sql-formatter")
|
||||
:args `("-l" ,my/sqlformatter-dialect))
|
||||
|
||||
(my-leader-def
|
||||
:keymaps '(sql-mode-map)
|
||||
"rr" #'sqlformat-buffer)
|
||||
|
||||
(use-package sparql-mode
|
||||
:straight t)
|
||||
|
||||
(use-package org
|
||||
:straight (:type built-in)
|
||||
:if (not my/remote-server)
|
||||
|
|
@ -2903,6 +2914,20 @@ Returns (<buffer> . <workspace-index>) or nil."
|
|||
"C-c t A" #'org-transclusion-add-all
|
||||
"C-c t t" #'org-transclusion-mode))
|
||||
|
||||
(defun my/export-org-tables-to-csv ()
|
||||
(interactive)
|
||||
(org-table-map-tables
|
||||
(lambda ()
|
||||
(when-let
|
||||
(name
|
||||
(plist-get (cadr (org-element-at-point)) :name))
|
||||
(org-table-export
|
||||
(concat
|
||||
(file-name-directory
|
||||
(buffer-file-name))
|
||||
name ".csv")
|
||||
"orgtbl-to-csv")))))
|
||||
|
||||
(defun my/update-org-agenda ()
|
||||
(interactive)
|
||||
(let ((project-files
|
||||
|
|
@ -2919,11 +2944,11 @@ Returns (<buffer> . <workspace-index>) or nil."
|
|||
,@project-files))
|
||||
(setq org-refile-targets
|
||||
`(,@(mapcar
|
||||
(lambda (f) `(,f . (:maxlevel . 2)))
|
||||
project-files)
|
||||
,@(mapcar
|
||||
(lambda (f) `(,f . (:tag . "refile")))
|
||||
project-files)))))
|
||||
project-files)))
|
||||
(when (file-exists-p (concat org-directory "/scripts/refile.el"))
|
||||
(load-file (concat org-directory "/scripts/refile.el"))
|
||||
(run-hooks 'my/org-refile-hooks))))
|
||||
|
||||
(with-eval-after-load-norem 'org
|
||||
(setq org-roam-directory (concat org-directory "/roam"))
|
||||
|
|
@ -2931,12 +2956,6 @@ Returns (<buffer> . <workspace-index>) or nil."
|
|||
;; (setq org-default-notes-file (concat org-directory "/notes.org"))
|
||||
)
|
||||
|
||||
(my-leader-def
|
||||
:infix "o"
|
||||
"" '(:which-key "org-mode")
|
||||
"c" 'org-capture
|
||||
"a" 'org-agenda)
|
||||
|
||||
(setq org-refile-use-outline-path 'file)
|
||||
(setq org-outline-path-complete-in-steps nil)
|
||||
|
||||
|
|
@ -2963,12 +2982,6 @@ Returns (<buffer> . <workspace-index>) or nil."
|
|||
,(concat "* %?\n"
|
||||
"/Entered on/ %U"))))
|
||||
|
||||
(with-eval-after-load-norem 'org
|
||||
(add-to-list 'org-global-properties
|
||||
'("Effort_ALL" . "0 0:05 0:10 0:15 0:30 0:45 1:00 2:00 4:00")))
|
||||
|
||||
(setq org-log-done 'time)
|
||||
|
||||
(use-package org-ql
|
||||
:after (org)
|
||||
:if (not my/remote-server)
|
||||
|
|
@ -2982,14 +2995,11 @@ Returns (<buffer> . <workspace-index>) or nil."
|
|||
(format-time-string "%Y-%m-%d" scheduled)
|
||||
"")))
|
||||
|
||||
(setq org-agenda-hide-tags-regexp (rx (or "org" "log" "log_here" "refile")))
|
||||
(setq org-agenda-hide-tags-regexp (rx (or "org" "refile")))
|
||||
|
||||
(setq org-agenda-custom-commands
|
||||
`(("p" "My outline"
|
||||
((agenda "")
|
||||
(todo "NEXT"
|
||||
((org-agenda-prefix-format " %i %-12:c [%e] ")
|
||||
(org-agenda-overriding-header "Next tasks")))
|
||||
(tags-todo "inbox"
|
||||
((org-agenda-overriding-header "Inbox")
|
||||
(org-agenda-prefix-format " %i %-12:c")
|
||||
|
|
@ -2999,37 +3009,100 @@ Returns (<buffer> . <workspace-index>) or nil."
|
|||
(org-agenda-hide-tags-regexp "waitlist")
|
||||
(org-agenda-prefix-format " %i %-12:c %-12(my/org-scheduled-get-time)")))))))
|
||||
|
||||
(use-package org-ref
|
||||
:straight (:files (:defaults (:exclude "*helm*")))
|
||||
:if (not my/remote-server)
|
||||
:init
|
||||
(setq bibtex-dialect 'biblatex)
|
||||
(setq bibtex-completion-bibliography '("~/Documents/org-mode/library.bib"))
|
||||
(setq bibtex-completion-library-path '("~/Documents/library"))
|
||||
(setq bibtex-completion-notes-path "~/Documents/org-mode/literature-notes")
|
||||
(setq bibtex-completion-display-formats
|
||||
'((t . "${author:36} ${title:*} ${note:10} ${year:4} ${=has-pdf=:1}${=type=:7}")))
|
||||
(setq bibtex-completion-pdf-open-function
|
||||
(lambda (file)
|
||||
(start-process "dired-open" nil
|
||||
"xdg-open" (file-truename file))))
|
||||
:after (org)
|
||||
:config
|
||||
(require 'org-ref-ivy)
|
||||
(general-define-key
|
||||
:keymaps 'org-mode-map
|
||||
"C-c l" #'org-ref-insert-link-hydra/body)
|
||||
(general-define-key
|
||||
:keymaps 'bibtex-mode-map
|
||||
"M-RET" 'org-ref-bibtex-hydra/body))
|
||||
(my-leader-def
|
||||
:infix "o"
|
||||
"" '(:which-key "org-mode")
|
||||
"c" 'org-capture
|
||||
"a" 'org-agenda)
|
||||
|
||||
(use-package ivy-bibtex
|
||||
:commands (ivy-bibtex)
|
||||
:straight t
|
||||
:init
|
||||
(my-leader-def "fB" 'ivy-bibtex))
|
||||
(with-eval-after-load-norem 'org
|
||||
(add-to-list 'org-global-properties
|
||||
'("Effort_ALL" . "0 0:05 0:10 0:15 0:30 0:45 1:00 2:00 4:00")))
|
||||
|
||||
(add-hook 'bibtex-mode 'smartparens-mode)
|
||||
(setq org-log-done 'time)
|
||||
|
||||
(defun my/org-clone-subtree-with-time-shift (n &optional shift)
|
||||
(interactive "nNumber of clones to produce: ")
|
||||
(unless (wholenump n) (user-error "Invalid number of replications %s" n))
|
||||
(when (org-before-first-heading-p) (user-error "No subtree to clone"))
|
||||
(let* ((beg (save-excursion (org-back-to-heading t) (point)))
|
||||
(end-of-tree (save-excursion (org-end-of-subtree t t) (point)))
|
||||
(shift
|
||||
(or shift
|
||||
(if (and (not (equal current-prefix-arg '(4)))
|
||||
(save-excursion
|
||||
(goto-char beg)
|
||||
(re-search-forward org-ts-regexp-both end-of-tree t)))
|
||||
(read-from-minibuffer
|
||||
"Date shift per clone (e.g. +1w, empty to copy unchanged): ")
|
||||
""))) ;No time shift
|
||||
(doshift
|
||||
(and (org-string-nw-p shift)
|
||||
(or (string-match "\\`[ \t]*\\([+-]?[0-9]+\\)\\([hdwmy]\\)[ \t]*\\'"
|
||||
shift)
|
||||
(user-error "Invalid shift specification %s" shift)))))
|
||||
(goto-char end-of-tree)
|
||||
(unless (bolp) (insert "\n"))
|
||||
(let* ((end (point))
|
||||
(template (buffer-substring beg end))
|
||||
(shift-n (and doshift (string-to-number (match-string 1 shift))))
|
||||
(shift-what (pcase (and doshift (match-string 2 shift))
|
||||
(`nil nil)
|
||||
("h" 'hour)
|
||||
("d" 'day)
|
||||
("w" (setq shift-n (* 7 shift-n)) 'day)
|
||||
("m" 'month)
|
||||
("y" 'year)
|
||||
(_ (error "Unsupported time unit"))))
|
||||
(nmin 1)
|
||||
(nmax n)
|
||||
(n-no-remove -1)
|
||||
(org-id-overriding-file-name (buffer-file-name (buffer-base-buffer)))
|
||||
(idprop (org-entry-get beg "ID")))
|
||||
(when (and doshift
|
||||
(string-match-p "<[^<>\n]+ [.+]?\\+[0-9]+[hdwmy][^<>\n]*>"
|
||||
template))
|
||||
(delete-region beg end)
|
||||
(setq end beg)
|
||||
(setq nmin 0)
|
||||
(setq nmax (1+ nmax))
|
||||
(setq n-no-remove nmax))
|
||||
(goto-char end)
|
||||
(cl-loop for n from nmin to nmax do
|
||||
(insert
|
||||
;; Prepare clone.
|
||||
(with-temp-buffer
|
||||
(insert template)
|
||||
(org-mode)
|
||||
(goto-char (point-min))
|
||||
(org-show-subtree)
|
||||
(and idprop (if org-clone-delete-id
|
||||
(org-entry-delete nil "ID")
|
||||
(org-id-get-create t)))
|
||||
(unless (= n 0)
|
||||
(while (re-search-forward org-clock-line-re nil t)
|
||||
(delete-region (line-beginning-position)
|
||||
(line-beginning-position 2)))
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward org-drawer-regexp nil t)
|
||||
(org-remove-empty-drawer-at (point))))
|
||||
(goto-char (point-min))
|
||||
|
||||
(when doshift
|
||||
(while (re-search-forward org-ts-regexp-both nil t)
|
||||
(org-timestamp-change (* n shift-n) shift-what))
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(evil-numbers/inc-at-pt (* n shift-n) (point-min)))
|
||||
(unless (= n n-no-remove)
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward org-ts-regexp nil t)
|
||||
(save-excursion
|
||||
(goto-char (match-beginning 0))
|
||||
(when (looking-at "<[^<>\n]+\\( +[.+]?\\+[0-9]+[hdwmy]\\)")
|
||||
(delete-region (match-beginning 1) (match-end 1)))))))
|
||||
(buffer-string)))))
|
||||
(goto-char beg)))
|
||||
|
||||
(use-package org-journal
|
||||
:straight t
|
||||
|
|
@ -3112,6 +3185,38 @@ Returns (<buffer> . <workspace-index>) or nil."
|
|||
(add-hook 'org-journal-after-entry-create-hook
|
||||
#'my/set-journal-header)
|
||||
|
||||
(use-package org-ref
|
||||
:straight (:files (:defaults (:exclude "*helm*")))
|
||||
:if (not my/remote-server)
|
||||
:init
|
||||
(setq bibtex-dialect 'biblatex)
|
||||
(setq bibtex-completion-bibliography '("~/Documents/org-mode/library.bib"))
|
||||
(setq bibtex-completion-library-path '("~/Documents/library"))
|
||||
(setq bibtex-completion-notes-path "~/Documents/org-mode/literature-notes")
|
||||
(setq bibtex-completion-display-formats
|
||||
'((t . "${author:36} ${title:*} ${note:10} ${year:4} ${=has-pdf=:1}${=type=:7}")))
|
||||
(setq bibtex-completion-pdf-open-function
|
||||
(lambda (file)
|
||||
(start-process "dired-open" nil
|
||||
"xdg-open" (file-truename file))))
|
||||
:after (org)
|
||||
:config
|
||||
(require 'org-ref-ivy)
|
||||
(general-define-key
|
||||
:keymaps 'org-mode-map
|
||||
"C-c l" #'org-ref-insert-link-hydra/body)
|
||||
(general-define-key
|
||||
:keymaps 'bibtex-mode-map
|
||||
"M-RET" 'org-ref-bibtex-hydra/body))
|
||||
|
||||
(use-package ivy-bibtex
|
||||
:commands (ivy-bibtex)
|
||||
:straight t
|
||||
:init
|
||||
(my-leader-def "fB" 'ivy-bibtex))
|
||||
|
||||
(add-hook 'bibtex-mode 'smartparens-mode)
|
||||
|
||||
(use-package emacsql-sqlite
|
||||
:defer t
|
||||
:if (not my/remote-server)
|
||||
|
|
@ -3424,103 +3529,6 @@ Returns (<buffer> . <workspace-index>) or nil."
|
|||
(setq org-contacts-files (list
|
||||
(concat org-directory "/contacts.org"))))
|
||||
|
||||
(defun my/export-org-tables-to-csv ()
|
||||
(interactive)
|
||||
(org-table-map-tables
|
||||
(lambda ()
|
||||
(when-let
|
||||
(name
|
||||
(plist-get (cadr (org-element-at-point)) :name))
|
||||
(org-table-export
|
||||
(concat
|
||||
(file-name-directory
|
||||
(buffer-file-name))
|
||||
name ".csv")
|
||||
"orgtbl-to-csv")))))
|
||||
|
||||
(defun my/org-clone-subtree-with-time-shift (n &optional shift)
|
||||
(interactive "nNumber of clones to produce: ")
|
||||
(unless (wholenump n) (user-error "Invalid number of replications %s" n))
|
||||
(when (org-before-first-heading-p) (user-error "No subtree to clone"))
|
||||
(let* ((beg (save-excursion (org-back-to-heading t) (point)))
|
||||
(end-of-tree (save-excursion (org-end-of-subtree t t) (point)))
|
||||
(shift
|
||||
(or shift
|
||||
(if (and (not (equal current-prefix-arg '(4)))
|
||||
(save-excursion
|
||||
(goto-char beg)
|
||||
(re-search-forward org-ts-regexp-both end-of-tree t)))
|
||||
(read-from-minibuffer
|
||||
"Date shift per clone (e.g. +1w, empty to copy unchanged): ")
|
||||
""))) ;No time shift
|
||||
(doshift
|
||||
(and (org-string-nw-p shift)
|
||||
(or (string-match "\\`[ \t]*\\([+-]?[0-9]+\\)\\([hdwmy]\\)[ \t]*\\'"
|
||||
shift)
|
||||
(user-error "Invalid shift specification %s" shift)))))
|
||||
(goto-char end-of-tree)
|
||||
(unless (bolp) (insert "\n"))
|
||||
(let* ((end (point))
|
||||
(template (buffer-substring beg end))
|
||||
(shift-n (and doshift (string-to-number (match-string 1 shift))))
|
||||
(shift-what (pcase (and doshift (match-string 2 shift))
|
||||
(`nil nil)
|
||||
("h" 'hour)
|
||||
("d" 'day)
|
||||
("w" (setq shift-n (* 7 shift-n)) 'day)
|
||||
("m" 'month)
|
||||
("y" 'year)
|
||||
(_ (error "Unsupported time unit"))))
|
||||
(nmin 1)
|
||||
(nmax n)
|
||||
(n-no-remove -1)
|
||||
(org-id-overriding-file-name (buffer-file-name (buffer-base-buffer)))
|
||||
(idprop (org-entry-get beg "ID")))
|
||||
(when (and doshift
|
||||
(string-match-p "<[^<>\n]+ [.+]?\\+[0-9]+[hdwmy][^<>\n]*>"
|
||||
template))
|
||||
(delete-region beg end)
|
||||
(setq end beg)
|
||||
(setq nmin 0)
|
||||
(setq nmax (1+ nmax))
|
||||
(setq n-no-remove nmax))
|
||||
(goto-char end)
|
||||
(cl-loop for n from nmin to nmax do
|
||||
(insert
|
||||
;; Prepare clone.
|
||||
(with-temp-buffer
|
||||
(insert template)
|
||||
(org-mode)
|
||||
(goto-char (point-min))
|
||||
(org-show-subtree)
|
||||
(and idprop (if org-clone-delete-id
|
||||
(org-entry-delete nil "ID")
|
||||
(org-id-get-create t)))
|
||||
(unless (= n 0)
|
||||
(while (re-search-forward org-clock-line-re nil t)
|
||||
(delete-region (line-beginning-position)
|
||||
(line-beginning-position 2)))
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward org-drawer-regexp nil t)
|
||||
(org-remove-empty-drawer-at (point))))
|
||||
(goto-char (point-min))
|
||||
|
||||
(when doshift
|
||||
(while (re-search-forward org-ts-regexp-both nil t)
|
||||
(org-timestamp-change (* n shift-n) shift-what))
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(evil-numbers/inc-at-pt (* n shift-n) (point-min)))
|
||||
(unless (= n n-no-remove)
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward org-ts-regexp nil t)
|
||||
(save-excursion
|
||||
(goto-char (match-beginning 0))
|
||||
(when (looking-at "<[^<>\n]+\\( +[.+]?\\+[0-9]+[hdwmy]\\)")
|
||||
(delete-region (match-beginning 1) (match-end 1)))))))
|
||||
(buffer-string)))))
|
||||
(goto-char beg)))
|
||||
|
||||
(use-package org-latex-impatient
|
||||
:straight (:repo "yangsheng6810/org-latex-impatient"
|
||||
:branch "master"
|
||||
|
|
@ -5255,13 +5263,6 @@ ENTRY is an instance of `elfeed-entry'."
|
|||
"Q" 'google-translate-query-translate-reverse
|
||||
"t" 'google-translate-smooth-translate)
|
||||
|
||||
(use-package reverso
|
||||
:straight (:host github :repo "SqrtMinusOne/reverso.el")
|
||||
:init
|
||||
(my-leader-def "ar" #'reverso)
|
||||
:config
|
||||
(setq reverso-languages '(russian english german)))
|
||||
|
||||
(use-package tldr
|
||||
:straight t
|
||||
:commands (tldr)
|
||||
|
|
|
|||
654
Emacs.org
654
Emacs.org
|
|
@ -8,7 +8,7 @@
|
|||
#+begin_quote
|
||||
One day we won't hate one another, no young boy will march to war and I will clean up my Emacs config. But that day isn't today.
|
||||
#+end_quote
|
||||
- Me, <2021-05-27 Thu 17:35> in commit 93a0573 T_T
|
||||
- Me, <2021-05-27 Thu 17:35> in commit 93a0573. Adapted from [[https://www.youtube.com/watch?v=pIdBinlW40E][The Dark Element - "The Pallbearer Walks Alone"]]. T_T
|
||||
|
||||
* Introduction
|
||||
My configuration of [[https://www.gnu.org/software/emacs/][GNU Emacs]], an awesome +text editor+ program that can do almost anything.
|
||||
|
|
@ -55,7 +55,8 @@ I decided not to keep configs for features that I do not use anymore because thi
|
|||
| svelte-mode | 8594d6f53e42c70bbf903e168607841854818a38 |
|
||||
| pomidor | 8594d6f53e42c70bbf903e168607841854818a38 |
|
||||
| elfeed-score | 8e591e0d2afd909ae5be00caf17f9b17c6cd8b61 |
|
||||
* Bootstrap
|
||||
| org-trello | 3f5967a5f63928ea9c8567d8d9f31e84cdbbc21f |
|
||||
* Initial setup
|
||||
Setting up the environment, performance tuning and a few basic settings.
|
||||
|
||||
First things first, lexical binding.
|
||||
|
|
@ -2951,6 +2952,17 @@ References:
|
|||
"p" 'langtool-goto-previous-error
|
||||
"l" 'langtool-correct-buffer)
|
||||
#+end_src
|
||||
*** Reverso
|
||||
[[https://github.com/SqrtMinusOne/reverso.el][reverso.el]] is a package of mine that provides Emacs interface for [[https://reverso.net]].
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package reverso
|
||||
:straight (:host github :repo "SqrtMinusOne/reverso.el")
|
||||
:init
|
||||
(my-leader-def "ar" #'reverso)
|
||||
:config
|
||||
(setq reverso-languages '(russian english german)))
|
||||
#+end_src
|
||||
** Lisp
|
||||
[[file:dot-imgs/lisp_cycles.png]]
|
||||
|
||||
|
|
@ -3044,12 +3056,13 @@ Python requirements:
|
|||
(add-hook 'scheme-mode-hook #'lispy-mode)
|
||||
#+end_src
|
||||
*** CLIPS
|
||||
An honorary Lisp
|
||||
An honorary Lisp.
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package clips-mode
|
||||
:straight t
|
||||
:mode "\\.cl\\'"
|
||||
:disabled t
|
||||
:config
|
||||
(add-hook 'clips-mode 'lispy-mode))
|
||||
#+end_src
|
||||
|
|
@ -3348,6 +3361,44 @@ A package to quickly create =.gitignore= files.
|
|||
:config
|
||||
(add-hook 'fish-mode-hook #'smartparens-mode))
|
||||
#+end_src
|
||||
** Query languages
|
||||
*** SQL
|
||||
[[https://github.com/zeroturnaround/sql-formatter][sql-formatter]] is a nice JavaScript package for pretty-printing SQL queries. It is not packaged for Emacs, so the easiest way to use it seems to be to define a custom formatter via [[https://github.com/purcell/emacs-reformatter][reformatter]].
|
||||
|
||||
Also, I've made a simple function to switch dialects because I often alternate between them.
|
||||
|
||||
So far I didn't find a nice SQL client for Emacs, but I occasionally run SQL queries in Org Mode, so this quite package is handy.
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(setq my/sqlformatter-dialect-choice
|
||||
'("db2" "mariadb" "mysql" "n1ql" "plsql" "postgresql" "redshift" "spark" "sql" "tsql"))
|
||||
|
||||
(setq my/sqlformatter-dialect "postgresql")
|
||||
|
||||
(defun my/sqlformatter-set-dialect ()
|
||||
"Set dialect for sql-formatter"
|
||||
(interactive)
|
||||
(setq my/sqlformatter-dialect
|
||||
(completing-read "Dialect: " my/sqlformatter-dialect-choice)))
|
||||
|
||||
(reformatter-define sqlformat
|
||||
:program (executable-find "sql-formatter")
|
||||
:args `("-l" ,my/sqlformatter-dialect))
|
||||
|
||||
(my-leader-def
|
||||
:keymaps '(sql-mode-map)
|
||||
"rr" #'sqlformat-buffer)
|
||||
#+end_src
|
||||
*** SPARQL
|
||||
#+begin_src emacs-lisp
|
||||
(use-package sparql-mode
|
||||
:straight t)
|
||||
#+end_src
|
||||
*** GraphQL
|
||||
#+begin_src emacs-lisp
|
||||
(use-package graphql-mode
|
||||
:straight t)
|
||||
#+end_src
|
||||
** x509
|
||||
#+begin_src emacs-lisp
|
||||
(use-package x509-mode
|
||||
|
|
@ -3429,40 +3480,8 @@ A package to quickly create =.gitignore= files.
|
|||
|
||||
(my/set-smartparens-indent 'lua-mode)
|
||||
#+end_src
|
||||
** SQL
|
||||
[[https://github.com/zeroturnaround/sql-formatter][sql-formatter]] is a nice JavaScript package for pretty-printing SQL queries. It is not packaged for Emacs, so the easiest way to use it seems to be to define a custom formatter via [[https://github.com/purcell/emacs-reformatter][reformatter]].
|
||||
|
||||
Also, I've made a simple function to switch dialects because I often alternate between them.
|
||||
|
||||
So far I didn't find a nice SQL client for Emacs, but I occasionally run SQL queries in Org Mode, so this quite package is handy.
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(setq my/sqlformatter-dialect-choice
|
||||
'("db2" "mariadb" "mysql" "n1ql" "plsql" "postgresql" "redshift" "spark" "sql" "tsql"))
|
||||
|
||||
(setq my/sqlformatter-dialect "postgresql")
|
||||
|
||||
(defun my/sqlformatter-set-dialect ()
|
||||
"Set dialect for sql-formatter"
|
||||
(interactive)
|
||||
(setq my/sqlformatter-dialect
|
||||
(completing-read "Dialect: " my/sqlformatter-dialect-choice)))
|
||||
|
||||
(reformatter-define sqlformat
|
||||
:program (executable-find "sql-formatter")
|
||||
:args `("-l" ,my/sqlformatter-dialect))
|
||||
|
||||
(my-leader-def
|
||||
:keymaps '(sql-mode-map)
|
||||
"rr" #'sqlformat-buffer)
|
||||
#+end_src
|
||||
** SPARQL
|
||||
#+begin_src emacs-lisp
|
||||
(use-package sparql-mode
|
||||
:straight t)
|
||||
#+end_src
|
||||
* Org Mode
|
||||
*Org mode* is a tool that leverages plain-text files for various tasks like making notes, literate programming, task management, etc.
|
||||
*Org mode* is a tool that leverages plain-text files for tasks like making notes, literate programming, task management, etc.
|
||||
|
||||
References:
|
||||
- [[https://orgmode.org/][Org Mode homepage]]
|
||||
|
|
@ -3496,7 +3515,7 @@ Use the built-in org mode (=:type built-in=).
|
|||
#+end_src
|
||||
|
||||
*** Encryption
|
||||
Setting up =org-crypt= to encrypt a part of a file.
|
||||
Setting up =org-crypt= to encrypt parts of file.
|
||||
|
||||
#+begin_src emacs-lisp :noweb-ref
|
||||
(with-eval-after-load-norem 'org
|
||||
|
|
@ -3506,9 +3525,9 @@ Setting up =org-crypt= to encrypt a part of a file.
|
|||
(setq org-crypt-key "C1EC867E478472439CC82410DE004F32AFA00205"))
|
||||
#+end_src
|
||||
|
||||
This enables encryption for Org segments which are tagged =:crypt:=.
|
||||
This enables encryption for Org segments tagged =:crypt:=.
|
||||
|
||||
Another way to encrypt org files is to save them with extension =.org.gpg=. That way by default epa always prompts for a key, which is not what I want when there is in fact only one key to select. So I make the following advice:
|
||||
Another way to encrypt Org files is to save them with the extension =.org.gpg=. However, by default [[https://www.gnu.org/software/emacs/manual/html_mono/epa.html][EPA]] always prompts for the key, which is not what I want when there is only one key to select. Hence the following advice:
|
||||
#+begin_src emacs-lisp
|
||||
(defun my/epa--select-keys-around (fun prompt keys)
|
||||
(if (= (seq-length keys) 1)
|
||||
|
|
@ -3525,7 +3544,7 @@ Another way to encrypt org files is to save them with extension =.org.gpg=. That
|
|||
=org-contrib= is a package with various additions to Org. I use the following:
|
||||
- =ox-extra= - extensions for org export
|
||||
|
||||
This used to have =org-contacts= and =ol-notmuch= at some point, but they've been migrated to separate repos since.
|
||||
This used to have =org-contacts= and =ol-notmuch= at some point, but they have since been migrated to separate repos.
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package org-contrib
|
||||
|
|
@ -3910,9 +3929,9 @@ Some keybindings:
|
|||
#+end_src
|
||||
|
||||
*** Managing a literate programming project
|
||||
A few tricks to do literate programming.
|
||||
A few tricks to do literate programming. I actually have only one ([[https://github.com/SqrtMinusOne/sqrt-data][sqrt-data]]), and I'm not convinced in the benefits of the approach...
|
||||
|
||||
I prefer to put the org files to a separate directory (e.g. =org=). So I've come up with the following solution to avoid manually prefixing the =:tangle= arguments.
|
||||
Anyway, Org files are better off in a separated directory (e.g. =org=). So I've come up with the following solution to avoid manually prefixing the =:tangle= arguments.
|
||||
|
||||
Set up the following argument with the path to the project root:
|
||||
#+begin_example
|
||||
|
|
@ -4038,16 +4057,56 @@ A package that implements transclusions in Org Mode, i.e. rendering part of one
|
|||
"C-c t A" #'org-transclusion-add-all
|
||||
"C-c t t" #'org-transclusion-mode))
|
||||
#+end_src
|
||||
** Productivity & Knowledge management
|
||||
My ongoing effort to get a productivity setup in Org.
|
||||
*** Managing tables
|
||||
I use Org to manage some small tables which I want to process further. So here is a function that saves each table to a CSV file.
|
||||
|
||||
Some inspiration:
|
||||
#+begin_src emacs-lisp
|
||||
(defun my/export-org-tables-to-csv ()
|
||||
(interactive)
|
||||
(org-table-map-tables
|
||||
(lambda ()
|
||||
(when-let
|
||||
(name
|
||||
(plist-get (cadr (org-element-at-point)) :name))
|
||||
(org-table-export
|
||||
(concat
|
||||
(file-name-directory
|
||||
(buffer-file-name))
|
||||
name ".csv")
|
||||
"orgtbl-to-csv")))))
|
||||
#+end_src
|
||||
** Productivity & Knowledge management
|
||||
My ongoing effort to +get a productivity setup+ manage something in my life in Org.
|
||||
|
||||
Initial inspirations (<2021-06-30 Wed>):
|
||||
- [[https://www.labri.fr/perso/nrougier/GTD/index.html][Nicolas P. Rougier. Get Things Done with Emacs]]
|
||||
- [[https://blog.jethro.dev/posts/org_mode_workflow_preview/][Jetro Kuan. Org-mode Workflow]]
|
||||
- [[https://www.alexeyshmalko.com/how-i-note/][Alexey Shmalko: How I note]]
|
||||
- [[https://rgoswami.me/posts/org-note-workflow/][Rohit Goswami: An Orgmode Note Workflow]]
|
||||
|
||||
Used files:
|
||||
Some later reflections (<2023-01-04 Wed>): so, it's been one year and a half... I've tried some things since writing the initial inspiration list.
|
||||
|
||||
[[*Org Journal][Org Journal]] and [[*Org Roam][Org Roam]] are probably the most relevant packages in my workflow now.
|
||||
|
||||
For [[*Org Agenda][project management]] I've ended up doing more or less plain Org files & Org Agenda. I don't feel I'd extract much benefit from a more "advanced" system, with effort estimation, atomic tasks, etc. Less is more, I guess. Besided, I'm not particularly excited about the part of my life that may require such management.
|
||||
|
||||
Neither I felt I was doing anything meaningful with my attempts at regular [[*Review workflow][review workflow]]. I'll think what to do with the section a bit latet.
|
||||
|
||||
*** Org Agenda & Project Management
|
||||
I tried some things for generic project management, including:
|
||||
- Managing projects in Org Roam
|
||||
- Syncing with Trello
|
||||
- Effort estimation & more atomic tasks
|
||||
- Writing down progress on projects with =org-journal-tags=
|
||||
- ...
|
||||
|
||||
But for now stopped on one =.org= file for one large project / a few smaller related projects and rather high-level tasks. Don't feel the need to do more yet.
|
||||
|
||||
**** Agenda & refile files
|
||||
All my project files live in the =/projects= directory, so here's a function to set up =org-agenda-files= and =org-refile-targets= accordingly.
|
||||
|
||||
Also, my project structure is somewhat chaotic, so I have an =.el= file in the org directory that defines some of the refile targets.
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(defun my/update-org-agenda ()
|
||||
(interactive)
|
||||
|
|
@ -4065,11 +4124,11 @@ Used files:
|
|||
,@project-files))
|
||||
(setq org-refile-targets
|
||||
`(,@(mapcar
|
||||
(lambda (f) `(,f . (:maxlevel . 2)))
|
||||
project-files)
|
||||
,@(mapcar
|
||||
(lambda (f) `(,f . (:tag . "refile")))
|
||||
project-files)))))
|
||||
project-files)))
|
||||
(when (file-exists-p (concat org-directory "/scripts/refile.el"))
|
||||
(load-file (concat org-directory "/scripts/refile.el"))
|
||||
(run-hooks 'my/org-refile-hooks))))
|
||||
|
||||
(with-eval-after-load-norem 'org
|
||||
(setq org-roam-directory (concat org-directory "/roam"))
|
||||
|
|
@ -4078,22 +4137,14 @@ Used files:
|
|||
)
|
||||
#+end_src
|
||||
|
||||
Hotkeys
|
||||
#+begin_src emacs-lisp
|
||||
(my-leader-def
|
||||
:infix "o"
|
||||
"" '(:which-key "org-mode")
|
||||
"c" 'org-capture
|
||||
"a" 'org-agenda)
|
||||
#+end_src
|
||||
|
||||
Refile targets
|
||||
Refile settings
|
||||
#+begin_src emacs-lisp
|
||||
(setq org-refile-use-outline-path 'file)
|
||||
(setq org-outline-path-complete-in-steps nil)
|
||||
#+end_src
|
||||
|
||||
*** Capture templates & various settings
|
||||
**** Capture templates & various settings
|
||||
Settings for Org capture mode. The goal here is to have a non-disruptive process to capture various ideas.
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
|
|
@ -4121,6 +4172,55 @@ Settings for Org capture mode. The goal here is to have a non-disruptive process
|
|||
"/Entered on/ %U"))))
|
||||
#+end_src
|
||||
|
||||
**** org-ql
|
||||
[[https://github.com/alphapapa/org-ql][org-ql]] is a package to query the org files. I've tried using it for:
|
||||
- Grabbing done tasks / meetings / etc for review workflow
|
||||
- Adding Trello tasks into Agenga
|
||||
|
||||
None of that worked out, but I'll keep the package here in case I have some more ideas.
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package org-ql
|
||||
:after (org)
|
||||
:if (not my/remote-server)
|
||||
:straight (:fetcher github
|
||||
:repo "alphapapa/org-ql"
|
||||
:files (:defaults (:exclude "helm-org-ql.el"))))
|
||||
#+end_src
|
||||
**** Custom agendas
|
||||
Some custom agendas to fit my workflow.
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(defun my/org-scheduled-get-time ()
|
||||
(let ((scheduled (org-get-scheduled-time (point))))
|
||||
(if scheduled
|
||||
(format-time-string "%Y-%m-%d" scheduled)
|
||||
"")))
|
||||
|
||||
(setq org-agenda-hide-tags-regexp (rx (or "org" "refile")))
|
||||
|
||||
(setq org-agenda-custom-commands
|
||||
`(("p" "My outline"
|
||||
((agenda "")
|
||||
(tags-todo "inbox"
|
||||
((org-agenda-overriding-header "Inbox")
|
||||
(org-agenda-prefix-format " %i %-12:c")
|
||||
(org-agenda-hide-tags-regexp ".")))
|
||||
(tags-todo "+waitlist+SCHEDULED<=\"<+14d>\""
|
||||
((org-agenda-overriding-header "Waitlist")
|
||||
(org-agenda-hide-tags-regexp "waitlist")
|
||||
(org-agenda-prefix-format " %i %-12:c %-12(my/org-scheduled-get-time)")))))))
|
||||
#+end_src
|
||||
**** Other settings
|
||||
Hotkeys
|
||||
#+begin_src emacs-lisp
|
||||
(my-leader-def
|
||||
:infix "o"
|
||||
"" '(:which-key "org-mode")
|
||||
"c" 'org-capture
|
||||
"a" 'org-agenda)
|
||||
#+end_src
|
||||
|
||||
Effort estimation
|
||||
#+begin_src emacs-lisp
|
||||
(with-eval-after-load-norem 'org
|
||||
|
|
@ -4132,147 +4232,119 @@ Log DONE time
|
|||
#+begin_src emacs-lisp
|
||||
(setq org-log-done 'time)
|
||||
#+end_src
|
||||
*** OFF (OFF) Trello sync
|
||||
UPD <2022-03-27 Sun>: disabling this for now.
|
||||
**** Copying records
|
||||
I like to add numbers to repeating events, like meetings. E.g.
|
||||
|
||||
Some of the projects I'm participating in are managed via Trello, so I use [[http://org-trello.github.io/][org-trello]] to keep track of them. The package has a remarkably awkward keybindings setup, so my effort to call =my-leader-def= to set keybindings I like is no less awkward.
|
||||
#+begin_example
|
||||
,* Job meeting 62
|
||||
SCHEDULED: <2022-11-13 16:00>
|
||||
,* Job meeting 63
|
||||
SCHEDULED: <2022-11-13 16:00>
|
||||
...
|
||||
#+end_example
|
||||
|
||||
Also, trello files are huge and have a lot of information and tasks which do not concern me, so I don't add them to =org-agenda-files=.
|
||||
Naturally, I want a way to copy such records. Org Mode already has a function called =org-clone-subtree-with-time-shift=, that does everything I want except for updating the numbers.
|
||||
|
||||
#+begin_src emacs-lisp :tangle no
|
||||
(unless (file-exists-p (concat org-directory "/trello"))
|
||||
(mkdir (concat org-directory "/trello") t))
|
||||
|
||||
(setq org-trello-files
|
||||
(thread-last (concat org-directory "/trello")
|
||||
(directory-files)
|
||||
(seq-filter
|
||||
(lambda (f) (string-match-p (rx ".org" eos) f)))
|
||||
(mapcar
|
||||
(lambda (f) (concat org-directory "/trello/" f)))))
|
||||
#+end_src
|
||||
|
||||
#+begin_src emacs-lisp :tangle no
|
||||
(use-package org-trello
|
||||
:straight (:build (:not native-compile))
|
||||
:commands (org-trello-mode)
|
||||
:disabled
|
||||
:if (not my/remote-server)
|
||||
:init
|
||||
(setq org-trello-current-prefix-keybinding "C-c o")
|
||||
(setq org-trello-add-tags nil)
|
||||
|
||||
(add-hook 'org-mode-hook
|
||||
(lambda ()
|
||||
(when (string-match-p (rx "trello") (or (buffer-file-name) ""))
|
||||
(org-trello-mode))))
|
||||
:config
|
||||
(eval
|
||||
`(my-leader-def
|
||||
:infix "o t"
|
||||
:keymaps '(org-trello-mode-map)
|
||||
"" '(:which-key "trello")
|
||||
,@(mapcan
|
||||
(lambda (b) (list (nth 1 b) (macroexp-quote (nth 0 b))))
|
||||
org-trello-interactive-command-binding-couples))))
|
||||
#+end_src
|
||||
*** org-ql
|
||||
[[https://github.com/alphapapa/org-ql][org-ql]] is a package to query the org files. I'm using it in my review workflow and for custom agenda views.
|
||||
Unfortunately, I see no way to advise the original function, so here's my version that makes use of =evil-numbers=:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package org-ql
|
||||
:after (org)
|
||||
:if (not my/remote-server)
|
||||
:straight (:fetcher github
|
||||
:repo "alphapapa/org-ql"
|
||||
:files (:defaults (:exclude "helm-org-ql.el"))))
|
||||
#+end_src
|
||||
*** Custom agendas
|
||||
Some custom agendas to fit my workflow.
|
||||
(defun my/org-clone-subtree-with-time-shift (n &optional shift)
|
||||
(interactive "nNumber of clones to produce: ")
|
||||
(unless (wholenump n) (user-error "Invalid number of replications %s" n))
|
||||
(when (org-before-first-heading-p) (user-error "No subtree to clone"))
|
||||
(let* ((beg (save-excursion (org-back-to-heading t) (point)))
|
||||
(end-of-tree (save-excursion (org-end-of-subtree t t) (point)))
|
||||
(shift
|
||||
(or shift
|
||||
(if (and (not (equal current-prefix-arg '(4)))
|
||||
(save-excursion
|
||||
(goto-char beg)
|
||||
(re-search-forward org-ts-regexp-both end-of-tree t)))
|
||||
(read-from-minibuffer
|
||||
"Date shift per clone (e.g. +1w, empty to copy unchanged): ")
|
||||
""))) ;No time shift
|
||||
(doshift
|
||||
(and (org-string-nw-p shift)
|
||||
(or (string-match "\\`[ \t]*\\([+-]?[0-9]+\\)\\([hdwmy]\\)[ \t]*\\'"
|
||||
shift)
|
||||
(user-error "Invalid shift specification %s" shift)))))
|
||||
(goto-char end-of-tree)
|
||||
(unless (bolp) (insert "\n"))
|
||||
(let* ((end (point))
|
||||
(template (buffer-substring beg end))
|
||||
(shift-n (and doshift (string-to-number (match-string 1 shift))))
|
||||
(shift-what (pcase (and doshift (match-string 2 shift))
|
||||
(`nil nil)
|
||||
("h" 'hour)
|
||||
("d" 'day)
|
||||
("w" (setq shift-n (* 7 shift-n)) 'day)
|
||||
("m" 'month)
|
||||
("y" 'year)
|
||||
(_ (error "Unsupported time unit"))))
|
||||
(nmin 1)
|
||||
(nmax n)
|
||||
(n-no-remove -1)
|
||||
(org-id-overriding-file-name (buffer-file-name (buffer-base-buffer)))
|
||||
(idprop (org-entry-get beg "ID")))
|
||||
(when (and doshift
|
||||
(string-match-p "<[^<>\n]+ [.+]?\\+[0-9]+[hdwmy][^<>\n]*>"
|
||||
template))
|
||||
(delete-region beg end)
|
||||
(setq end beg)
|
||||
(setq nmin 0)
|
||||
(setq nmax (1+ nmax))
|
||||
(setq n-no-remove nmax))
|
||||
(goto-char end)
|
||||
(cl-loop for n from nmin to nmax do
|
||||
(insert
|
||||
;; Prepare clone.
|
||||
(with-temp-buffer
|
||||
(insert template)
|
||||
(org-mode)
|
||||
(goto-char (point-min))
|
||||
(org-show-subtree)
|
||||
(and idprop (if org-clone-delete-id
|
||||
(org-entry-delete nil "ID")
|
||||
(org-id-get-create t)))
|
||||
(unless (= n 0)
|
||||
(while (re-search-forward org-clock-line-re nil t)
|
||||
(delete-region (line-beginning-position)
|
||||
(line-beginning-position 2)))
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward org-drawer-regexp nil t)
|
||||
(org-remove-empty-drawer-at (point))))
|
||||
(goto-char (point-min))
|
||||
|
||||
+Despite the fact that I don't add =org-trello-files= to =org-agenda-files= I still want to see them in agenda, so I use =org-ql-block= from =org-ql=.+
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(defun my/org-scheduled-get-time ()
|
||||
(let ((scheduled (org-get-scheduled-time (point))))
|
||||
(if scheduled
|
||||
(format-time-string "%Y-%m-%d" scheduled)
|
||||
"")))
|
||||
|
||||
(setq org-agenda-hide-tags-regexp (rx (or "org" "log" "log_here" "refile")))
|
||||
|
||||
(setq org-agenda-custom-commands
|
||||
`(("p" "My outline"
|
||||
((agenda "")
|
||||
(todo "NEXT"
|
||||
((org-agenda-prefix-format " %i %-12:c [%e] ")
|
||||
(org-agenda-overriding-header "Next tasks")))
|
||||
(tags-todo "inbox"
|
||||
((org-agenda-overriding-header "Inbox")
|
||||
(org-agenda-prefix-format " %i %-12:c")
|
||||
(org-agenda-hide-tags-regexp ".")))
|
||||
(tags-todo "+waitlist+SCHEDULED<=\"<+14d>\""
|
||||
((org-agenda-overriding-header "Waitlist")
|
||||
(org-agenda-hide-tags-regexp "waitlist")
|
||||
(org-agenda-prefix-format " %i %-12:c %-12(my/org-scheduled-get-time)")))))))
|
||||
#+end_src
|
||||
*** Bibliography
|
||||
I'm currently trying to use [[https://www.zotero.org/][Zotero]] to manage my bibliograhy.
|
||||
|
||||
There is a Zotero extension called [[https://retorque.re/zotero-better-bibtex/][better bibtex]], which allows for having one bibtex file that is always syncronized with the library. That comes quite handy for Emacs integration.
|
||||
|
||||
**** org-ref
|
||||
|
||||
[[https://github.com/jkitchin/org-ref][org-ref]] is an excellent package by John Kitchin that provides support for managing citations and references in Org Mode.
|
||||
|
||||
It may have become less relevant since =org-cite= was merged into plain Org, but =org-ref= is still just as usable.
|
||||
|
||||
As of now, this package loads Helm on start. To avoid this, I have to exclude Helm from the =Package-requires= in the [[file:.emacs.d/straight/repos/org-ref/org-ref.el][org-ref.el]] file. I haven't found a way to do this without modifying the package source yet.
|
||||
|
||||
There's a package called [[https://github.com/org-roam/org-roam-bibtex][org-roam-bibtex]] that allows to keep literature notes in [[https://github.com/org-roam/org-roam][org-roam]] and access them from =org-ref=, but as for now I store literature notes separately, as advised by Ahrens Sönke in his excellent book "How to take smart notes".
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package org-ref
|
||||
:straight (:files (:defaults (:exclude "*helm*")))
|
||||
:if (not my/remote-server)
|
||||
:init
|
||||
(setq bibtex-dialect 'biblatex)
|
||||
(setq bibtex-completion-bibliography '("~/Documents/org-mode/library.bib"))
|
||||
(setq bibtex-completion-library-path '("~/Documents/library"))
|
||||
(setq bibtex-completion-notes-path "~/Documents/org-mode/literature-notes")
|
||||
(setq bibtex-completion-display-formats
|
||||
'((t . "${author:36} ${title:*} ${note:10} ${year:4} ${=has-pdf=:1}${=type=:7}")))
|
||||
(setq bibtex-completion-pdf-open-function
|
||||
(lambda (file)
|
||||
(start-process "dired-open" nil
|
||||
"xdg-open" (file-truename file))))
|
||||
:after (org)
|
||||
:config
|
||||
(require 'org-ref-ivy)
|
||||
(general-define-key
|
||||
:keymaps 'org-mode-map
|
||||
"C-c l" #'org-ref-insert-link-hydra/body)
|
||||
(general-define-key
|
||||
:keymaps 'bibtex-mode-map
|
||||
"M-RET" 'org-ref-bibtex-hydra/body))
|
||||
(when doshift
|
||||
(while (re-search-forward org-ts-regexp-both nil t)
|
||||
(org-timestamp-change (* n shift-n) shift-what))
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(evil-numbers/inc-at-pt (* n shift-n) (point-min)))
|
||||
(unless (= n n-no-remove)
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward org-ts-regexp nil t)
|
||||
(save-excursion
|
||||
(goto-char (match-beginning 0))
|
||||
(when (looking-at "<[^<>\n]+\\( +[.+]?\\+[0-9]+[hdwmy]\\)")
|
||||
(delete-region (match-beginning 1) (match-end 1)))))))
|
||||
(buffer-string)))))
|
||||
(goto-char beg)))
|
||||
#+end_src
|
||||
|
||||
**** ivy-bibtex
|
||||
[[https://github.com/tmalsburg/helm-bibtex][ivy-bibtex]] is an Ivy interface to bibtex. It uses the same configuration variables as =org-ref=, or rather, both packages use variables from the built-in =bibtex.el=
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package ivy-bibtex
|
||||
:commands (ivy-bibtex)
|
||||
:straight t
|
||||
:init
|
||||
(my-leader-def "fB" 'ivy-bibtex))
|
||||
|
||||
(add-hook 'bibtex-mode 'smartparens-mode)
|
||||
#+end_src
|
||||
My addition to that is the form with =evil-numbers/inc-at-pt=.
|
||||
*** Org Journal
|
||||
[[https://github.com/bastibe/org-journal][org-journal]] is a plugin for maintaining a journal in org mode. I want(ed) to have its entries separate from my knowledge base.
|
||||
[[https://github.com/bastibe/org-journal][org-journal]] is a package for maintaining a journal in org mode.
|
||||
|
||||
I've tried switching to Org Roam Dailies, but in the end decided that org-journal fits my workflow better.
|
||||
This part turned out to be great. I even consulted the journal a few times to check if something actually happened, which makes me uneasy now that I think about it...
|
||||
|
||||
One issue I found is that it's kinda hard to find anything in the journal, and I'm not eager to open the journal for a random date anyway. So I've made a package called [[https://github.com/SqrtMinusOne/org-journal-tags][org-journal-tags]].
|
||||
|
||||
My initial desire was to be able to query the journal for my thoughts on a particular subject or theme, for progress on some project, or for records related to some person... Which is kinda useful, although not quite as much as I expected it to be. Relatively fast querying of the journal is also nice.
|
||||
|
||||
The section I named "on this day" turned out to be particularly interesting, as it kinda allowed me to connect with past versions of myself.
|
||||
|
||||
And it was interesting to find the reinforcement effect of checked dates on the calendar.
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package org-journal
|
||||
|
|
@ -4294,7 +4366,7 @@ I've tried switching to Org Roam Dailies, but in the end decided that org-journa
|
|||
(setq org-journal-enable-encryption t))
|
||||
#+end_src
|
||||
|
||||
[[https://github.com/SqrtMinusOne/org-journal-tags][org-journal-tags]] is my package that implements a tagging system for org-journal.
|
||||
So, [[https://github.com/SqrtMinusOne/org-journal-tags][org-journal-tags]] is my package that implements a tagging system for org-journal.
|
||||
#+begin_src emacs-lisp
|
||||
(use-package org-journal-tags
|
||||
:straight (:host github :repo "SqrtMinusOne/org-journal-tags")
|
||||
|
|
@ -4371,12 +4443,72 @@ And here's a function that creates a drawer with such information. At the moment
|
|||
(add-hook 'org-journal-after-entry-create-hook
|
||||
#'my/set-journal-header)
|
||||
#+end_src
|
||||
*** Bibliography
|
||||
I use [[https://www.zotero.org/][Zotero]] to manage my bibliograhy.
|
||||
|
||||
There is a Zotero extension called [[https://retorque.re/zotero-better-bibtex/][better bibtex]], which allows for having one bibtex file that is always syncronized with the library. That comes quite handy for Emacs integration.
|
||||
|
||||
**** org-ref
|
||||
[[https://github.com/jkitchin/org-ref][org-ref]] is an excellent package by John Kitchin that provides support for managing citations and references in Org Mode.
|
||||
|
||||
It may have become less relevant since =org-cite= was merged into plain Org, but =org-ref= is still just as usable.
|
||||
|
||||
As of now, this package loads Helm on start. To avoid this, I have to exclude Helm from the =Package-requires= in the [[file:.emacs.d/straight/repos/org-ref/org-ref.el][org-ref.el]] file. I haven't found a way to do this without modifying the package source yet.
|
||||
|
||||
There's a package called [[https://github.com/org-roam/org-roam-bibtex][org-roam-bibtex]] that allows to keep literature notes in [[https://github.com/org-roam/org-roam][org-roam]] and access them from =org-ref=, but as for now I store literature notes separately.
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package org-ref
|
||||
:straight (:files (:defaults (:exclude "*helm*")))
|
||||
:if (not my/remote-server)
|
||||
:init
|
||||
(setq bibtex-dialect 'biblatex)
|
||||
(setq bibtex-completion-bibliography '("~/Documents/org-mode/library.bib"))
|
||||
(setq bibtex-completion-library-path '("~/Documents/library"))
|
||||
(setq bibtex-completion-notes-path "~/Documents/org-mode/literature-notes")
|
||||
(setq bibtex-completion-display-formats
|
||||
'((t . "${author:36} ${title:*} ${note:10} ${year:4} ${=has-pdf=:1}${=type=:7}")))
|
||||
(setq bibtex-completion-pdf-open-function
|
||||
(lambda (file)
|
||||
(start-process "dired-open" nil
|
||||
"xdg-open" (file-truename file))))
|
||||
:after (org)
|
||||
:config
|
||||
(require 'org-ref-ivy)
|
||||
(general-define-key
|
||||
:keymaps 'org-mode-map
|
||||
"C-c l" #'org-ref-insert-link-hydra/body)
|
||||
(general-define-key
|
||||
:keymaps 'bibtex-mode-map
|
||||
"M-RET" 'org-ref-bibtex-hydra/body))
|
||||
#+end_src
|
||||
|
||||
**** ivy-bibtex
|
||||
[[https://github.com/tmalsburg/helm-bibtex][ivy-bibtex]] is an Ivy interface to bibtex. It uses the same configuration variables as =org-ref=, or rather, both packages use variables from the built-in =bibtex.el=
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package ivy-bibtex
|
||||
:commands (ivy-bibtex)
|
||||
:straight t
|
||||
:init
|
||||
(my-leader-def "fB" 'ivy-bibtex))
|
||||
|
||||
(add-hook 'bibtex-mode 'smartparens-mode)
|
||||
#+end_src
|
||||
*** Org Roam
|
||||
[[https://github.com/org-roam/org-roam][org-roam]] is a plain-text knowledge database.
|
||||
|
||||
Things I tried with Org Roam:
|
||||
- Managing projects. Ended up preferring plain Org.
|
||||
- Writing journal. =org-journal= and =org-journal-tags= seem to be a better fit for my workflow.
|
||||
- Writing a journal with =org-roam-dailies=.
|
||||
Didn't work out as I expected, so I've made =org-journal-tags= after I understood better what I want.
|
||||
|
||||
Regardless, it turned out to be great for managing Zettelkasten, which is the original purpose of the package anyway. I didn't expect to ever get into something like this, but I guess I was wrong.
|
||||
|
||||
Some resources that helped me along the way (and still help):
|
||||
- Sönke Ahrens' book "How to take smart notes"
|
||||
- https://zettelkasten.de/ - a lot of useful stuff here, especially in the "Getting Started" section.
|
||||
- [[https://www.youtube.com/watch?v=-TpWahIzueg][System Crafters Live! - Can You Apply Zettelkasten in Emacs?]]
|
||||
|
||||
**** Basic package configuration
|
||||
| Guix dependency |
|
||||
|
|
@ -4430,9 +4562,7 @@ Capture templates for =org-roam-capture=. As for now, nothing too complicated he
|
|||
**** Keybindings
|
||||
A set of keybindings to quickly access things in Org Roam.
|
||||
|
||||
I used to have multiple categories of nodes in Org Roam (projects, dailies, etc), but as of now, only Zettelkasten remains.
|
||||
#+begin_src emacs-lisp
|
||||
|
||||
(with-eval-after-load 'org-roam
|
||||
(my-leader-def
|
||||
:infix "or"
|
||||
|
|
@ -4464,7 +4594,9 @@ I used to have multiple categories of nodes in Org Roam (projects, dailies, etc)
|
|||
"C-c i" 'org-roam-node-insert))
|
||||
#+end_src
|
||||
**** Org Roam UI
|
||||
A browser frontend to visualize a Roam directory in a form of a graph.
|
||||
A browser frontend to visualize the Roam database as a graph.
|
||||
|
||||
Actually, I don't find this quite as useful as structure nodes, because over time my graph grew somewhat convoluted. But it looks impressive.
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package org-roam-ui
|
||||
|
|
@ -4493,7 +4625,7 @@ Don't forget to run the following after setup:
|
|||
xdg-mime default org-protocol.desktop x-scheme-handler/org-protocol
|
||||
#+end_src
|
||||
**** Deft
|
||||
[[https://github.com/jrblevin/deft][Deft]] is an Emacs package to quickly find notes. It seems quite useful to look for =org-roam= notes based on their contents.
|
||||
[[https://github.com/jrblevin/deft][Deft]] is an Emacs package to quickly find notes. I use it as a full-text search engine for =org-roam=.
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(use-package deft
|
||||
|
|
@ -4826,125 +4958,6 @@ An example contact entry can look like this:
|
|||
:BIRTHDAY: [1998-08-14]
|
||||
:END:
|
||||
#+end_example
|
||||
*** Managing tables
|
||||
I use Org to manage some small tables which I want to process further. So here is a function that saves each table to a CSV file.
|
||||
#+begin_src emacs-lisp
|
||||
(defun my/export-org-tables-to-csv ()
|
||||
(interactive)
|
||||
(org-table-map-tables
|
||||
(lambda ()
|
||||
(when-let
|
||||
(name
|
||||
(plist-get (cadr (org-element-at-point)) :name))
|
||||
(org-table-export
|
||||
(concat
|
||||
(file-name-directory
|
||||
(buffer-file-name))
|
||||
name ".csv")
|
||||
"orgtbl-to-csv")))))
|
||||
#+end_src
|
||||
*** Copying records
|
||||
I like to add numbers to repeating events, like meetings. E.g.
|
||||
|
||||
#+begin_example
|
||||
,* Job meeting 62
|
||||
SCHEDULED: <2022-11-13 16:00>
|
||||
,* Job meeting 63
|
||||
SCHEDULED: <2022-11-13 16:00>
|
||||
...
|
||||
#+end_example
|
||||
|
||||
Naturally, I want a way to copy such records. Org Mode already has a function called =org-clone-subtree-with-time-shift=, that does everything I want except for updating the numbers.
|
||||
|
||||
Unfortunately, I see no way to advise the original function, so here's my version that makes use of =evil-numbers=:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(defun my/org-clone-subtree-with-time-shift (n &optional shift)
|
||||
(interactive "nNumber of clones to produce: ")
|
||||
(unless (wholenump n) (user-error "Invalid number of replications %s" n))
|
||||
(when (org-before-first-heading-p) (user-error "No subtree to clone"))
|
||||
(let* ((beg (save-excursion (org-back-to-heading t) (point)))
|
||||
(end-of-tree (save-excursion (org-end-of-subtree t t) (point)))
|
||||
(shift
|
||||
(or shift
|
||||
(if (and (not (equal current-prefix-arg '(4)))
|
||||
(save-excursion
|
||||
(goto-char beg)
|
||||
(re-search-forward org-ts-regexp-both end-of-tree t)))
|
||||
(read-from-minibuffer
|
||||
"Date shift per clone (e.g. +1w, empty to copy unchanged): ")
|
||||
""))) ;No time shift
|
||||
(doshift
|
||||
(and (org-string-nw-p shift)
|
||||
(or (string-match "\\`[ \t]*\\([+-]?[0-9]+\\)\\([hdwmy]\\)[ \t]*\\'"
|
||||
shift)
|
||||
(user-error "Invalid shift specification %s" shift)))))
|
||||
(goto-char end-of-tree)
|
||||
(unless (bolp) (insert "\n"))
|
||||
(let* ((end (point))
|
||||
(template (buffer-substring beg end))
|
||||
(shift-n (and doshift (string-to-number (match-string 1 shift))))
|
||||
(shift-what (pcase (and doshift (match-string 2 shift))
|
||||
(`nil nil)
|
||||
("h" 'hour)
|
||||
("d" 'day)
|
||||
("w" (setq shift-n (* 7 shift-n)) 'day)
|
||||
("m" 'month)
|
||||
("y" 'year)
|
||||
(_ (error "Unsupported time unit"))))
|
||||
(nmin 1)
|
||||
(nmax n)
|
||||
(n-no-remove -1)
|
||||
(org-id-overriding-file-name (buffer-file-name (buffer-base-buffer)))
|
||||
(idprop (org-entry-get beg "ID")))
|
||||
(when (and doshift
|
||||
(string-match-p "<[^<>\n]+ [.+]?\\+[0-9]+[hdwmy][^<>\n]*>"
|
||||
template))
|
||||
(delete-region beg end)
|
||||
(setq end beg)
|
||||
(setq nmin 0)
|
||||
(setq nmax (1+ nmax))
|
||||
(setq n-no-remove nmax))
|
||||
(goto-char end)
|
||||
(cl-loop for n from nmin to nmax do
|
||||
(insert
|
||||
;; Prepare clone.
|
||||
(with-temp-buffer
|
||||
(insert template)
|
||||
(org-mode)
|
||||
(goto-char (point-min))
|
||||
(org-show-subtree)
|
||||
(and idprop (if org-clone-delete-id
|
||||
(org-entry-delete nil "ID")
|
||||
(org-id-get-create t)))
|
||||
(unless (= n 0)
|
||||
(while (re-search-forward org-clock-line-re nil t)
|
||||
(delete-region (line-beginning-position)
|
||||
(line-beginning-position 2)))
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward org-drawer-regexp nil t)
|
||||
(org-remove-empty-drawer-at (point))))
|
||||
(goto-char (point-min))
|
||||
|
||||
(when doshift
|
||||
(while (re-search-forward org-ts-regexp-both nil t)
|
||||
(org-timestamp-change (* n shift-n) shift-what))
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(evil-numbers/inc-at-pt (* n shift-n) (point-min)))
|
||||
(unless (= n n-no-remove)
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward org-ts-regexp nil t)
|
||||
(save-excursion
|
||||
(goto-char (match-beginning 0))
|
||||
(when (looking-at "<[^<>\n]+\\( +[.+]?\\+[0-9]+[hdwmy]\\)")
|
||||
(delete-region (match-beginning 1) (match-end 1)))))))
|
||||
(buffer-string)))))
|
||||
(goto-char beg)))
|
||||
#+end_src
|
||||
|
||||
My addition to that is the form with =evil-numbers/inc-at-pt=.
|
||||
|
||||
** UI
|
||||
*** OFF (OFF) Instant equations preview
|
||||
Instant math previews for org mode.
|
||||
|
|
@ -7443,15 +7456,6 @@ References:
|
|||
"Q" 'google-translate-query-translate-reverse
|
||||
"t" 'google-translate-smooth-translate)
|
||||
#+end_src
|
||||
*** Reverso
|
||||
#+begin_src emacs-lisp
|
||||
(use-package reverso
|
||||
:straight (:host github :repo "SqrtMinusOne/reverso.el")
|
||||
:init
|
||||
(my-leader-def "ar" #'reverso)
|
||||
:config
|
||||
(setq reverso-languages '(russian english german)))
|
||||
#+end_src
|
||||
** Reading documentation
|
||||
*** tldr
|
||||
[[https://tldr.sh/][tldr]] is a collaborative project providing cheatsheets for various console commands. For some reason, the built-in download in the package is broken, so I use my own function.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue