Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/alphapapa/alpha-org

A powerful Org configuration
https://github.com/alphapapa/alpha-org

emacs org-mode

Last synced: 3 months ago
JSON representation

A powerful Org configuration

Awesome Lists containing this project

README

        

#+TITLE: alpha-org

=alpha-org= is a powerful configuration for =org-mode=, similar to how [[http://spacemacs.org/][Spacemacs]] and [[https://github.com/hlissner/doom-emacs][Doom]] are configurations for Emacs as a whole.

* Screenshots

Theming is not included as part of this configuration; this is just an example showing =doom-nord=.

[[images/1.png]]

* Usage

This can be used as a package which you [[*Installation][install]], or, since each feature is configured in its own =use-package= block, you may copy parts into your own config.

** Installation

The easiest way to install the whole thing is with [[https://framagit.org/steckerhalter/quelpa-use-package][quelpa-use-package]] (which may be installed from [[https://melpa.org][MELPA]]), like so:

#+begin_src elisp :tangle no
(require 'quelpa-use-package)
(use-package alpha-org
:quelpa (alpha-org :fetcher github :repo "alphapapa/alpha-org"))
#+end_src

** Sandbox

The script [[https://github.com/alphapapa/emacs-sandbox.sh][emacs-sandbox.sh]] can be used to try this configuration in a sandbox, separately from your existing Emacs configuration, like this:

#+BEGIN_EXAMPLE
$ emacs-sandbox.sh README.org
#+END_EXAMPLE

After Emacs opens this file, follow the instructions in the =Installation= section above, or load the =alpha-org.el= library, e.g. with =M-x load-file RET alpha-org.el RET=.

** Key Bindings

To best demonstrate the power of this configuration, it's necessary to bind some keys by default (because using =M-x= to access everything is relatively cumbersome). While this config isn't designed to work with [[https://github.com/emacs-evil/evil][EVIL]], similar to Spacemacs and Doom, all keys bound by this config are under a [[*%5B%5Bhttps://github.com/noctuid/general.el%5D%5BGeneral%5D%5D][prefix key]], which is =M-SPC= by default.

+ Inserting
- Links
+ =M-SPC ilu= Insert link to URL at point or on clipboard with =org-web-tools=.
- Timestamps
+ =M-SPC it= Insert current, inactive timestamp.
+ =M-SPC iT= Insert current, active timestamp.
+ Headings
- =M-SPC ha= Go to heading in agenda files.
- =M-SPC hb= Go to heading in current buffer.
- =M-SPC hp= Go to parent of current heading.
- =M-SPC hr= Go to a recent heading.
- =M-SPC hv= Go to a visible heading.
+ Refiling
- =M-SPC rv= Refile current heading to any currently visible heading.
+ View
- =M-SPC vs= View default sidebars (=org-sidebar-toggle=).
- =M-SPC vt= View tree sidebar (=org-sidebar-tree-toggle=).

* DOING Tutorial / Demo

# These should probably be organized into sections by related features, e.g. search, sidebars, etc.

A step-by-step guide showing the use of some features would probably be helpful. Here's a start:

1. Install the =alpha-org= package.
2. Open this =README.org= file.
3. Press =M-SPC vt= to show the tree sidebar, and again to hide it.
4. Press =M-SPC vs= to show the item sidebar, and again to hide it.
5. Select the tree sidebar window and press == to globally cycle the tree's outline visibility. Press == or click =mouse-2= to cycle individual trees.
6. Click on a heading *(which one?)* with =mouse-1= in the tree sidebar to show that entry's contents.
7. Press =M-SPC vt= to show the tree sidebar for just that entry.
8. In the tree sidebar, click and drag the on a heading to show more of its contents. Try clicking and dragging with both =mouse-1= and =mouse-2=.

* Requirements

These packages must already be installed:

+ [[https://github.com/jwiegley/use-package][use-package]]

* Code
:PROPERTIES:
:header-args:elisp: :tangle alpha-org.el
:END:

** Header

This header is tangled to =alpha-org.el=, declaring package dependencies so that they can be installed automatically.

#+BEGIN_SRC elisp
;;; alpha-org.el --- A powerful Org configuration -*- lexical-binding: t; -*-

;; Author: Adam Porter
;; Keywords: outlines

;; Package-Requires: ((emacs "26.3") (use-package) (general) (avy) (which-key) (org-bullets) (org-make-toc) (org-sidebar) (org-sticky-header))

;;; License:

;; Copyright (C) 2019 Adam Porter

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see .

;;; Commentary:

;; `alpha-org' is a powerful configuration for `org-mode', similar to
;; how Spacemacs and Doom are configurations for Emacs as a whole.

;;; Code:

;;;; Requirements

(require 'use-package)

(require 'cl-lib)
(require 'subr-x)
#+END_SRC

** Non-Org

Code and packages that aren't directly Org-related.

*** [[https://github.com/noctuid/general.el][General]]

General is used to ease configuration of key bindings.

#+begin_src elisp
(use-package general
:config
(global-unset-key (kbd "M-SPC"))
(general-create-definer alpha-org/general-def
:prefix "M-SPC"))
#+end_src

**** TODO Prefix key variable?

Can I use a variable for this prefix key?

*** TODO which-key
*** MAYBE Hydra
*** MAYBE [[https://gitlab.com/jjzmajic/hercules.el][hercules]]

** Org

Code and packages that are directly Org-related.

*** Configuration

#+begin_src elisp
;;;; Configuration

;; This section includes configuration code for options and packages built-in to Org.
#+end_src

**** Appearance

#+BEGIN_SRC elisp
(use-package org
:custom (org-ellipsis "⋯"))
#+END_SRC

**** Lists

#+BEGIN_SRC elisp
(use-package org
:custom
(org-list-demote-modify-bullet '(("+" . "-") ("-" . "+"))))
#+END_SRC
**** Speed commands

Speed commands provide one-key bindings to quickly navigate and manipulate outlines.

#+begin_src elisp
(use-package org
:custom
(org-use-speed-commands (lambda ()
(and (looking-at org-outline-regexp)
(looking-back "^\**")))))
#+end_src

***** TODO Link to Org documentation for speed command keys
**** org-indent-mode

This mode displays text indented to match its heading's indentation. Text is not actually indented in the buffer.

#+BEGIN_SRC elisp
(add-hook 'org-mode-hook 'org-indent-mode)
#+END_SRC

***** TODO Comparison screenshot
*** Packages

These packages are included and configured by default. Each package links to its configuration code later in this file.

#+begin_src elisp
;;;; Packages
#+end_src

**** Contents

# Temporarily disabling the ToC here because sometimes it's annoying having it regenerated while I'm working on the file.
**** TODO Agenda [0/1]

***** TODO org-super-agenda

**** TODO Appearance / UI [0/2]

***** DOING org-sidebar

#+begin_src elisp
(use-package org-sidebar
:general
(alpha-org/general-def
"vs" #'org-sidebar-toggle
"vt" #'org-sidebar-tree-toggle)
:custom (org-sidebar-tree-side 'left))
#+end_src

***** TODO yequake

The ~yequake-org-capture~ function is used to provide a quick capturing UI with drop-down Emacs windows that disappear automatically when a capture is finalized or canceled.

***** [[https://github.com/emacsorphanage/org-bullets][org-bullets]]

This mode replaces heading stars with visually appealing ones. Its settings can be customized in the =org-bullets= group.

#+BEGIN_SRC elisp
(use-package org-bullets
:hook (org-mode . org-bullets-mode))
#+END_SRC

****** TODO Screenshot

***** [[https://github.com/alphapapa/org-sticky-header][org-sticky-header]]

This package displays in the header-line the Org heading for the node that’s at the top of the window. This way, if the heading for the text at the top of the window is beyond the top of the window, you don’t forget which heading the text belongs to. The display can be customized to show just the heading, the full outline path, or the full outline path in reverse.

#+BEGIN_SRC elisp
(use-package org-sticky-header
:hook (org-mode . org-sticky-header-mode))
#+END_SRC
****** TODO Screenshot

**** TODO Capture
***** TODO org-web-tools

#+BEGIN_SRC elisp
(use-package org-web-tools
:general
(alpha-org/general-def
"ilu" #'org-web-tools-link-for-url))
#+END_SRC

**** Headings
***** DONE org-recent-headings

#+BEGIN_SRC elisp
(use-package org-recent-headings
:general
(alpha-org/general-def
"hr" #'org-recent-headings-helm)
:config
(org-recent-headings-mode)
:custom
(org-recent-headings-reverse-paths t)
(org-recent-headings-candidate-number-limit 100))
#+END_SRC

***** TODO org-bookmark-heading

***** DONE helm-org

#+BEGIN_SRC elisp
(use-package helm-org
:general
(alpha-org/general-def
"ha" #'helm-org-agenda-files-headings
"hb" #'helm-org-in-buffer-headings
"hp" #'helm-org-parent-headings)
:custom
(helm-org-format-outline-path t))
#+END_SRC

**** Miscellaneous

***** DONE [[https://github.com/alphapapa/org-make-toc][org-make-toc]]

This package automates customizeable tables of contents in Org files.

#+BEGIN_SRC elisp
(use-package org-make-toc
:hook (org-mode . org-make-toc-mode))
#+END_SRC

***** MAYBE [[https://github.com/alphapapa/unpackaged.el][unpackaged]]

Not sure if I should use it or move its Org-related code into this.

***** DOING Avy

#+BEGIN_SRC elisp
(use-package avy
:general
(alpha-org/general-def
"hv" #'alpha-org/goto-visible-heading
"rv" #'alpha-org/refile-to-visible)

:config
(defun alpha-org/refile-to-visible ()
"Refile current heading as first child of visible heading selected with Avy."
;; Inspired by `org-teleport':
;; http://kitchingroup.cheme.cmu.edu/blog/2016/03/18/Org-teleport-headlines/
(interactive)
;; NOTE: Use `when-let' so that if avy is aborted with "C-g",
;; `org-refile' won't be called with a nil refile location.
(when-let ((marker (alpha-org/avy-marker)))
(let* ((filename (buffer-file-name (or (buffer-base-buffer
(marker-buffer marker))
(marker-buffer marker))))
(heading (org-with-point-at marker
(org-get-heading 'no-tags 'no-todo)))
;; NOTE: I guess this won't work with target buffers
;; whose filename is nil, but I doubt I'll ever want to
;; do that.
(rfloc (list heading filename nil marker))
(org-after-refile-insert-hook (cons #'org-reveal org-after-refile-insert-hook)))
(org-refile nil nil rfloc))))

(defun alpha-org/goto-visible-heading ()
"Go to visible heading selected with Avy."
(interactive)
(when-let* ((marker (alpha-org/avy-marker)))
(with-current-buffer (marker-buffer marker)
(goto-char marker))))

(defun alpha-org/avy-marker ()
"Return marker at Org heading selected with Avy."
(save-excursion
(when-let* ((org-reverse-note-order t)
(pos (avy-with avy-goto-line
(avy-jump (rx bol (1+ "*") (1+ blank))))))
(when (integerp (car pos))
;; If avy is aborted with "C-g", it returns
;; `t', so we know it was NOT aborted when it
;; returns an int. If it doesn't return an
;; int, we return nil.
(copy-marker (car pos)))))))
#+END_SRC

**** TODO Searching [0/5]

***** TODO org-ql

*** Other Code

**** TODO Tree-to-indirect-buffer command

My own function that works a bit better than the built-in one.

***** TODO Demo it

**** TODO Agenda for subtree command

***** TODO Demo it
**** TODO Outline tidying

My function that fixes blank lines between entries.
**** TODO =org-return-dwim=

Should demo this too.

**** TODO Refile within buffer

#+BEGIN_SRC elisp
(defun ap/org-refile-within-buffer ()
"Call `org-refile' with `org-refile-targets' set to current buffer's headings."
;; This works now, but it doesn't fontify the headings/paths like
;; Helm does, so it's faster but doesn't look as nice
(interactive)
(let ((org-refile-use-cache nil)
(org-refile-use-outline-path t)
(org-refile-targets (list (cons (list (buffer-file-name (or (buffer-base-buffer (current-buffer))
(current-buffer))))
(cons :maxlevel 20)))))
(call-interactively 'org-refile)))
#+END_SRC

** Footer

#+begin_src elisp
;;;; Footer

(provide 'alpha-org)

;;; alpha-org.el ends here

#+end_src

* Ideas

** MAYBE Organize code by features rather than packages

Users are more interested in features than what packages implement them. Even if a package were mentioned in more than one =use-package= form, it would still be helpful, because users could copy /features/ rather than whole /packages/ into their own configs.

** TODO Update tree sidebar with idle timer

e.g. to hide text from added entries (unless I can figure another way around that).

** MAYBE Use font-locking to hide entry content in tree sidebar

Suggested in a comment on Reddit. I think I noted it in =org-sidebar='s notes file.
** TODO Dim background of sidebar windows

Maybe something like [[https://github.com/mina86/auto-dim-other-buffers.el][auto-dim-other-buffers]].
** TODO Hook to update sidebar item buffers when file is saved

Seems like a natural way to update it, even if not optimal.

** TODO With prefix, insert timestamps with calendar prompt

** TODO =mouse-2= on headings in non-tree buffers to cycle visibility

** MAYBE Jump to characters/words with Avy

** TODO Include sandbox script for testing and demonstration

** TODO Demo =org-return-dwim=

** TODO Demo =org-sticky-header=

Show how scrolling down past the heading still shows it in the header line.

** MAYBE Scripted GIF screencast

Like [[https://github.com/alphapapa/org-ql/blob/master/images/demo-helm-org-ql.sh][this script]].

* Notes

** Discussions

*** [[https://www.reddit.com/r/orgmode/comments/dhzm0n/rfc_wip_alphaorg_a_configuration_like_spacemacs/][{RFC, WIP} alpha-org (a configuration like Spacemacs or Doom, but just for Org) : orgmode]]

* File Configuration

File-local configuration.

#+TODO: TODO DOING MAYBE | DONE CANCELLED

# Local Variables:
# after-save-hook: org-babel-tangle
# eval: (visual-line-mode)
# End: