org-basb-code icon indicating copy to clipboard operation
org-basb-code copied to clipboard

CODE methodology implementation with Emacs org-mode

#+TITLE: Emacs CODE implementation #+AUTHOR: Renat Galimov #+EXPORT_FILE_NAME: index

[[https://github.com/renatgalimov/org-basb-code/actions/workflows/ci.yml/badge.svg]]

  • CODE implementation :PROPERTIES: :DIR: ~/projects/org-basb-code/attachments/ :header-args: :tangle no :END:

https://renatgalimov.github.io/org-basb-code/

** How to work with this guide?

  • Copy-paste the [[#emacs-config][config]] source block at the end of this document into your =.emacs= file or into a file in your emacs directory.
  • In case of putting it into a separate file, add the following code to your emacs config file =(load-file "~/path/to/basb.el")=
  • If you want to try this setup on a fresh Emacs do the following:
    • Create a new directory inside of your HOME: =mkdir ~/.emacs.code.d=
    • Put there a new =init.el=: #+caption: Contents of ~/.emacs.code.d/CODE.el #+begin_src emacs-lisp (setq user-init-file (or load-file-name (buffer-file-name))) (setq user-emacs-directory (file-name-directory user-init-file)) (load-file "~/.emacs.code.d/CODE.el") #+end_src
    • Copy-paste the [[*Emacs config][config]] into a new ="~/.emacs.code.d/CODE.el"=
    • Load a fresh Emacs with =emacs -q --load ~/.emacs.code.d/init.el=
    • Emacs will download and install all the packages defined in this guide. You might need depelopment tools installed to compile some packages. File a bug with errors you get and I will extend this guide.
  • I will be using =C-c n= prefix for keybindings in this package.

** Prerequisites *** Pandoc

#+caption: Install Pandoc on Ubuntu #+begin_src bash :exports code :eval never-export sudo apt install pandoc #+end_src

#+caption: Install Pandoc on Mac OS with homebrew #+begin_src bash :exports code :eval never-export brew install pandoc #+end_src

Ensure that Pandoc is in your path.

#+caption: Pandoc version #+begin_src bash :exports both :eval never-export :results verbatim pandoc --version #+end_src

#+RESULTS: : pandoc 2.14.0.2 : Compiled with pandoc-types 1.22, texmath 0.12.3, skylighting 0.10.5.1, : citeproc 0.4.0.1, ipynb 0.1.0.1 : User data directory: /Users/renat.galimov/.local/share/pandoc : Copyright (C) 2006-2021 John MacFarlane. Web: https://pandoc.org : This is free software; see the source for copying conditions. There is no : warranty, not even for merchantability or fitness for a particular purpose.

*** melpa and melpa-stable We will be downloading packages from these repos

#+caption: Set up MELPA #+name: set-up-melpa #+begin_src emacs-lisp :exports code :eval never-export :results none (unless (boundp 'package-archives) (setq package-archives '()))

(let* ((no-ssl (and (memq system-type '(windows-nt ms-dos)) (not (gnutls-available-p)))) (proto (if no-ssl "http" "https"))) (add-to-list 'package-archives (cons "gnu" (concat proto "://elpa.gnu.org/packages/")) t) ;; (add-to-list 'package-archives (cons "nongnu" (concat proto "://elpa.nongnu.org/packages/")) t) (add-to-list 'package-archives (cons "melpa" (concat proto "://melpa.org/packages/")) t) (add-to-list 'package-archives (cons "melpa-stable" (concat proto "://stable.melpa.org/packages/")) t))

(package-refresh-contents)

(unless (bound-and-true-p package--initialized) (package-initialize)) #+end_src

*** straight.el

For this guide, we will be using [[https://github.com/raxod502/straight.el][straight.el]] as your package manager.

#+caption: Install straight.el #+name: install-straight-el #+begin_src emacs-lisp :exports code :eval never-export :results none (defvar bootstrap-version) (if (package-installed-p 'use-package) (eval-when-compile (require 'use-package)) (package-refresh-contents) (package-install 'use-package))

(unless (boundp 'straight-use-package)
  (message "Bootstrapping straight.el")
  (let ((bootstrap-file
         (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
        (bootstrap-version 5))
    (unless (file-exists-p bootstrap-file)
      (with-current-buffer
          (url-retrieve-synchronously
           "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
           'silent 'inhibit-cookies)
        (goto-char (point-max))
        (eval-print-last-sexp)))
    (load bootstrap-file nil 'nomessage))
  (message "Bootstrapping straight.el done"))

#+end_src

*** Org-roam Obviously, we need [[https://github.com/org-roam/org-roam][org-roam]] itself #+caption: Install org-roam #+name: install-org-roam #+begin_src emacs-lisp :exports code :eval never-export :results none (setq org-roam-v2-ack t) (use-package org-roam :after org :ensure t :pin "melpa-stable" :bind (("C-c n l" . #'org-roam-buffer-toggle) ("C-c n f" . #'org-roam-node-find) ("C-c n v" . #'org-roam-node-visit) ("C-c n i" . #'org-roam-node-insert) (("C-c q" . #'org-roam-tag-add)))

:config
;; We want org-id to work with our roam directory
(setq org-roam-file-extensions '("org" "org_archive")
      org-id-extra-files (org-roam-list-files)))

#+end_src

** Capture

#+begin_quote Emacs is a text editor. #+end_quote

*** Capture documents

  • Capture targets:
    • E-books

    • Documents

    • Videos

    • Audios

    • Images

      To capture we use Pandoc and [[https://github.com/tecosaur/org-pandoc-import][org-pandoc-import]]

      #+name: install-org-pandoc-import #+begin_src emacs-lisp (straight-use-package '(org-pandoc-import :host github :repo "tecosaur/org-pandoc-import" :files ("*.el" "filters" "preprocessors")))

      (global-set-key (kbd "C-c n o") #'org-pandoc-import-as-org) #+end_src

      Pandoc can convert almost any text format to org-mode representation. One of the current drawbacks - it cannot import online web pages.

*** Capture web-pages

**** org-web-tools [[https://github.com/alphapapa/org-web-tools][org-web-tools]] offers =org-web-tools-read-url-as-org= function, which can download an URL to an org buffer.

#+name: install-org-web-tools #+begin_src emacs-lisp (use-package org-web-tools :ensure t :pin "melpa-stable" :bind (("C-c n u" . org-web-tools-read-url-as-org))) #+end_src

Often, downloaded files need manual cleanup.

**** Firefox web-clipper and Pandoc

An alternative approach is to use a web-clipper and Pandoc.

  • Open the web article in your browser and activate a web-clipper. I use Firefoxes built-in one.

  • Save entire HTML into a file.

  • Convert the HTML with Pandoc #+caption: Convert HTML to Org with Pandoc #+begin_src bash pandoc -f html -t org .html -o .org #+end_src

    The resulting file might require some cleanup, but the quality of the output is the best among other methods.

*** Capture templates <<Please, contribute your capture templates>>

*** Finding your own records Crawling over your own notes is a key part of the project workflow.

Below I summarized information about all full-text search engines I found for org-mode.

Depending on your own need you might select one or multiple of them.

Unfortunately, I didn't find any ideal solution for a full-text search yet. Packages that make better sorting are slower than packages that give results fast but in a random order.

***** Org full-text search :table: :PROPERTIES: :ID: 47985238-3e66-4201-969c-16d1858b797e :COLUMNS: %25ITEM %FRONTEND %SPEED %SORT :END:

  • Requested features:
    • helm or counsel integration.

    • live search.

    • result previewing support.

    • a key-binding to capture results into currently clocked org file.

    • results ordering support

      • Headlines
      • Summary
      • Hightlight
    • large file-sets support

      #+CAPTION: Full text search engines features #+BEGIN: columnview :hlines 1 :id local :maxlevel 2 :indent t | ITEM | FRONTEND | SPEED | SORT | |---------------------------+----------+-------+------| | Org-roam Full-text search | | | | | _ ripgrep (helm-rg) | helm ivy | fast | nil | | _ helm-org-rifle | helm | slow | t | | _ deft | helm | fast | nil | | _ org-ql | helm | slow | | | _ recoll | helm ivy | fast | nil | | _ org-fts | ivy | fast | | | _ org-agenda search | | | | #+END:

******* ripgrep (helm-rg) :PROPERTIES: :frontend: helm ivy :full_text_search: t :speed: fast :sort: nil :END:

[[https://github.com/cosmicexplorer/helm-rg][GitHub - cosmicexplorer/helm-rg: ripgrep is nice]] Now I use it as a default text search engine.

#+caption: Install ripgrep in MacOS #+begin_src bash brew install ripgrep #+end_src

#+caption: Install helm-rg #+name: install-helm-rg #+begin_src emacs-lisp (use-package helm-rg :ensure t :after org-roam :pin "melpa-stable" :config (defun helm-rg-roam-directory (&optional query) "Search with rg in your roam directory, QUERY." (interactive) (let ((helm-rg-default-directory org-roam-directory) (helm-rg--current-dir org-roam-directory)) (helm-rg query nil))) :bind (("C-c n R" . helm-rg-roam-directory))) #+end_src

******* helm-org-rifle :PROPERTIES: :frontend: helm :speed: slow :sort: t :END:

[[https://github.com/alphapapa/org-rifle][GitHub - alphapapa/org-rifle: Rifle through your Org-mode buffers and acquire your target]]

This one is good. It gives you an idea about the context. But it's not ordering the data by the highlights.

I find org-rifle too slow at the moment. But its output is exacly what I want.

#+caption: Install org-rifle #+name: install-org-rifle #+begin_src emacs-lisp :comments both (use-package helm-org-rifle :ensure t :after org-roam :pin "melpa-stable" :config (defun org-rifle-roam-directory () (interactive) (helm-org-rifle-directories org-roam-directory)) :bind (("C-c n s" . org-rifle-roam-directory))) #+end_src

******* deft :PROPERTIES: :frontend: helm :speed: fast :sort: nil :END: [[https://github.com/dfeich/helm-deft][GitHub - dfeich/helm-deft: A helm based Emacs module to help search in a predetermined list of directories. Inspired by the deft module.]]

Helm implementation didn't work for me. So I set a default version here.

One of the drawbacks here is that you can't see the text you matched. From my point of view - helm-rg gives more precise information about the context.

#+name: install-deft #+begin_src emacs-lisp (use-package deft :ensure t :after org-roam :config (setq deft-directory org-roam-directory deft-recursive t) :bind (("C-c n d" . deft))) ;; (use-package helm-deft ;; :ensure t ;; :straight (:host github ;; :repo "dfeich/helm-deft" ;; :files ("*.el")) ;; :config ;; (setq helm-deft-dir-list `(,org-roam-directory) ;; helm-deft-extension '("org")) ;; :bind (("C-c n d" . helm-deft)))

#+end_src

******* org-ql :PROPERTIES: :frontend: helm :speed: slow :END: [[https://github.com/alphapapa/org-ql][GitHub - alphapapa/org-ql: An Org-mode query language, including search commands and saved views]]

Doesn't look suitable for large filesets, but helm implementation is good for medium-sized collections.

#+name: install-org-ql #+begin_src emacs-lisp (use-package org-ql :ensure t :after org :config (progn (message "Loading org-ql") (setq org-ql-search-directories-files-recursive t org-ql-search-directories-files-regexp ".org\(_archive\)?$")) )

(use-package helm-org-ql :ensure t :after org-ql :config (setq helm-org-ql-recursive-paths t) :bind (("C-c n q" . helm-org-ql-org-directory))) #+end_src ******* recoll :PROPERTIES: :frontend: helm ivy :speed: fast :sort: nil :END: [[https://github.com/emacs-helm/helm-recoll][GitHub - emacs-helm/helm-recoll: helm interface for the recoll desktop search tool.]] I found recoll being to hard to set up. I wasn't able to get it working on MacOS.

******* org-fts :PROPERTIES: :speed: fast :frontend: ivy :END: [[https://github.com/zot/microfts/tree/main/elisp][microfts/elisp at main · zot/microfts · GitHub]]

  • It didn't work on MacOS from scratch.
  • I tried to compile its binary manually but that didn't work either.
  • This one looks promising. Let's keep an eye on it.

******* org-agenda search

  • Not trying this for now because agenda wants to open all its files for search.

** Organize *** Org-mode tags

This is a default method. You just tag your projects with a =project= tag, areas with an =area= tag and so on.

You can search projects with helm or with org-ql:

#+caption: Finding projects with helm [[file:Emacs_CODE_implementation/2021-07-04_07-52-17_screenshot.png]]

#+caption: Finding projects with org-ql [[file:Emacs_CODE_implementation/2021-07-04_07-57-55_screenshot.png]]

*** Org-roam links

An alternative to use Org-roam references as tags. You create notebooks called: =projects=, =areas=, =resources= and insert a link to the target record according to where it belongs.

#+caption: Links to an area within notes [[file:Emacs_CODE_implementation/2021-07-04_08-05-12_screenshot.png]]

If you go to the =areas= note and call =org-roam-buffer-toggle=, you will see a backlink to you note in the side buffer.

#+caption: Backlinks to all areas in the side buffer [[file:Emacs_CODE_implementation/2021-07-04_08-07-11_screenshot.png]]

*** Org-roam-ui

A nice second-brain visualizator: [[https://github.com/org-roam/org-roam-ui][org-roam-ui]].

#+caption: org-roam-ui design #+attr_org: :width 400px [[file:Emacs_CODE_implementation/2021-11-03_21-44-11_screenshot.png]]

#+caption: Install org-roam-ui #+name: install-org-roam-ui #+begin_src elisp :exports code :eval never-export :results none (use-package org-roam-ui :ensure t :after org-roam ;; normally we'd recommend hooking orui after org-roam, but since org-roam does not have ;; a hookable mode anymore, you're advised to pick something yourself ;; if you don't care about startup time, use :hook (after-init . org-roam-ui-mode)

:config
(setq org-roam-ui-sync-theme t
      org-roam-ui-follow t
      org-roam-ui-update-on-save t
      org-roam-ui-open-on-start t))

#+end_src

** Distill *** Progressive summarization **** Make org-emphasize multi-linear

To bypass the limit of two lines for org-emphasize marks enable the code below.

#+name: increase-org-emphasis-limit #+begin_src emacs-lisp ;; Make org-emphasis to work on up to 10 lines selection. (setcar (nthcdr 4 org-emphasis-regexp-components) 10) (org-set-emph-re 'org-emphasis-regexp-components org-emphasis-regexp-components) #+end_src

**** Highlighting :LOGBOOK: CLOCK: [2021-06-13 Вс 07:16]--[2021-06-13 Sun 07:31] => 0:15 CLOCK: [2021-06-13 Вс 06:49]--[2021-06-13 Вс 07:15] => 0:26 :END:

Highlighting is a key part of progressive summarization. Here I will be highlighting with =highlight.el= and enriched mode. If you don't want to put your text file into the [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Enriched-Mode.html][enriched text mode]], you can use =org-emphasize= instead of functions provided here.

***** highlight.el

When working with plain text buffers, like org-mode or markdown, you can use [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Enriched-Mode.html][enriched text mode]] with the =highlight= library to mark the text.

#+caption: Set up highlight.el #+name: setup-highlight-el #+begin_src emacs-lisp ;; If you get errors saying somethign about facemenu, try ;; uncommenting this. ;; (setq facemenu-menu nil)

(use-package highlight :ensure t :config (defun hlt-general() (interactive) (unless (bound-and-true-p enriched-mode) (enriched-mode t)) (hlt-highlight-region (region-beginning) (region-end) 'highlight))

;; Without this setq highlights won't be saved even in enriched mode
(setq hlt-use-overlays-flag nil)

:bind (("C-c n h" . hlt-general)
       ("C-c n H" . hlt-unhighlight-region)))

;; If you cannot save your enriched files because of the :inherit ;; error, try uncommenting this function.

;; (defun enriched-face-ans (face) ;; "Return annotations specifying FACE. ;; FACE may be a list of faces instead of a single face; ;; it can also be anything allowed as an element of a list ;; which can be the value of the `face' text property." ;; (cond ((and (consp face) (eq (car face) 'foreground-color)) ;; (list (list "x-color" (cdr face)))) ;; ((and (consp face) (eq (car face) 'background-color)) ;; (list (list "x-bg-color" (cdr face)))) ;; ((and (listp face) (eq (car face) :foreground)) ;; (list (list "x-color" (cadr face)))) ;; ((and (listp face) (eq (car face) :background)) ;; (list (list "x-bg-color" (cadr face)))) ;; ((and (listp face) (eq (car face) :inherit)) ;; (enriched-face-ans (cdr face))) ;; ((listp face) ;; (apply 'append (mapcar 'enriched-face-ans face))) ;; ((let* ((fg (face-attribute face :foreground)) ;; (bg (face-attribute face :background)) ;; (props (face-font face t)) ;; (ans (cdr (format-annotate-single-property-change ;; 'face nil props enriched-translations)))) ;; (unless (eq fg 'unspecified) ;; (setq ans (cons (list "x-color" fg) ans))) ;; (unless (eq bg 'unspecified) ;; (setq ans (cons (list "x-bg-color" bg) ans))) ;; ans)))) #+end_src

***** org-capture a region :ATTACH: :PROPERTIES: :ID: 1FD14535-77E8-4296-9BC9-A72DB1CB7E0F :DIR: ~/projects/org-basb-code/attachments :END:

To keep track of highlighted notes we will use =org-capture=.

#+caption: A capture template #+name: highlight-capture #+begin_src elisp ;; Use =org-capture f= to put a link to the text you selected.into an ;; org entry with the current timer enabled.

(defun r/org-capture-get-selected-text () (with-current-buffer (org-capture-get :original-buffer) (string-trim (replace-regexp-in-string "\n" " " (cond ((eq major-mode 'pdf-view-mode) (pdf-info-gettext (pdf-view-current-page) (car (pdf-view-active-region)))) (t (buffer-substring-no-properties (region-beginning) (region-end)))))))) (defun r/org-capture-get-link (path) (with-current-buffer (org-capture-get :original-buffer) (cond ((eq major-mode 'pdf-view-mode) (switch-to-buffer (org-capture-get :original-buffer)) (org-pdftools-get-link)) (t (concat path "::" (r/org-capture-get-selected-text))))))

(with-eval-after-load "org-capture" (add-to-list 'org-capture-templates '("f" "Curently watched" item (clock) "%(r/org-capture-get-selected-text) [[%(r/org-capture-get-link "%F")][↗]]%?" :unnarrowed t)))

;; The code below automatically highlights the region we captured (defun do-highlight-on-capture () "Highlight selected region of the buffer you were in at capture." (save-excursion (with-current-buffer (plist-get org-capture-plist :original-buffer) (cond ((eq major-mode 'pdf-view-mode) (switch-to-buffer (org-capture-get :original-buffer)) (pdf-annot-add-highlight-markup-annotation (car (pdf-view-active-region)))) (t (hlt-general)))))) (defun highlight-on-capture () (when (equal (plist-get org-capture-plist :key) "f") (do-highlight-on-capture)))

(add-hook 'org-capture-after-finalize-hook #'highlight-on-capture) #+end_src

This is my basic marking mechanism. Whenever I'm reading an article in Emacs (transformed to an org-mode or markdown file), I click =C-c f= to insert an entry to the notebook I'm currently on.

#+caption: Highlighting on capture demo #+attr_org: :width 400px [[file:attachments/highlighting-with-org-capture.gif]] *** Working with PDF files :ATTACH: :PROPERTIES: :ID: B5A87A1B-E0FE-40D6-AC63-AD52DB283C31 :CUSTOM_ID: working-with-pdf-files :END:

Don't forget to install pdf-tools dependencies.

#+name: install glib on MacOS #+begin_src bash brew install glib #+end_src

#+name: install-pdf-tools #+begin_src emacs-lisp (use-package pdf-tools :ensure t :mode ("\.pdf\'" . pdf-view-mode) :init (require 'pdf-info) (condition-case nil (pdf-info-check-epdfinfo) (error (let ((default-directory (file-name-directory pdf-info-epdfinfo-program))) (pdf-tools-install t t)))))

(use-package org-pdftools :ensure t :hook (org-mode . org-pdftools-setup-link)) #+end_src ** Express This area is too large to cover it in this guide. If you're new to org-mode consult

[[https://orgmode.org/manual/Exporting.html][Exporting]] and [[https://orgmode.org/manual/Publishing.html][publishing]] sections of the org manual.

  • Emacs config :PROPERTIES: :CUSTOM_ID: emacs-config :END: #+caption: Config source block #+begin_src emacs-lisp :noweb yes :comments noweb :tangle (if (boundp 'org-basb-code-file) org-basb-code-file "~/emacs/CODE.el") <> <> <> <> <> <> <> <> <> <> <> <> <> <> #+end_src

  • Useful links

  • [[https://gist.github.com/mwfogleman/267b6bc7e512826a2c36cb57f0e3d854][GTD/BASB Templates for Emacs and Org-Mode · GitHub]]
  • [[yt:AyhPmypHDEw]]
  • [[https://github.com/weirdNox/org-noter][GitHub - weirdNox/org-noter: Emacs document annotator, using Org-mode]]
  • Improving this guide
  • [ ] per-org-document style

  • [ ] org-pdf-import videos for

    • [ ] epub
    • [ ] doc files
  • [ ] org web read url

  • [ ] fix invalid face error.

  • [ ] Faces not saving in enriched mode in vanilla emacs setup.

  • [ ] Links made by capture are broken.

  • [X] Use normal emacs

  • [ ] Org pdftools link

  • [ ] Capturing emails

  • [ ] Multi-line emphasis are not working on MacOS Emacs

  • [ ] Org pdftools: fix links for Linux and MacOS

  • [ ] Videos:

    Be slow when doing videos. Give more details?

    • [ ] Capturing different formats:
      • [ ] HTML
      • [ ] PDF
    • [ ] Organize: