├── README.org └── org-randomnote.el /README.org: -------------------------------------------------------------------------------- 1 | [[https://melpa.org/#/org-randomnote][file:https://melpa.org/packages/org-randomnote-badge.svg]] 2 | 3 | ~org-randomnote~ intends to provide a way to bring randomness into your Org-Mode workflow. It does so by implementing the "Random Note" functionality popularized by Tiago Forte with Evernote in Emacs Org-Mode. 4 | 5 | Some people use Random Note functionality daily, as a way to revisit nearly-forgotten but potentially-useful notes, or to spark creative insights by bringing older subjects into mind with new subjects. 6 | 7 | ** Installation and Configuration 8 | You can now use Melpa as usual: ~M-x package-install~ and then ~org-randomnote~. 9 | 10 | You can also use this example configuration, using John Wiegley's ~use-package~: 11 | 12 | #+BEGIN_SRC emacs-lisp 13 | (use-package org-randomnote 14 | :ensure t 15 | :bind ("C-c r" . org-randomnote)) 16 | #+END_SRC 17 | 18 | Then run ~eval-buffer~ on your ~.emacs~, or restart Emacs. 19 | 20 | In Spacemacs, you can put the ~use-package~ snippet above into ~dotspacemacs/user-config~, and add ~org-randomnote~ to your ~dotspacemacs-additional-packages~: 21 | 22 | #+BEGIN_SRC emacs-lisp 23 | dotspacemacs-additional-packages '( 24 | org-randomnote 25 | ) 26 | #+END_SRC 27 | 28 | Then use ~SPC-f-e-R~ to synchronize your Spacemacs and load the package. 29 | 30 | ** Usage 31 | Once loaded, run the interactive command ~org-randomnote~. 32 | 33 | You can configure which files ~org-randomnote~ selects from with the variable ~org-randomnote-candidates~. It defaults to using ~org-agenda-files~, but you can use any list of files: 34 | 35 | #+BEGIN_SRC emacs-lisp 36 | (setq org-randomnote-candidates '("~/org/todo.org")) 37 | #+END_SRC 38 | 39 | If you'd like to move to a random note on the current buffer only, use ~'current-buffer~. 40 | 41 | #+BEGIN_SRC emacs-lisp 42 | (setq org-randomnote-candidates 'current-buffer) 43 | #+END_SRC 44 | 45 | You can also configure the behavior with which ~org-randomnote~ opens files. By default, it simply moves to a random note's header. However, you can also configure it to use an indirect buffer, like so: 46 | 47 | #+BEGIN_SRC emacs-lisp 48 | (setq org-randomnote-open-behavior 'indirect-buffer) 49 | #+END_SRC 50 | 51 | To configure ~org-randomnote~ to use entire directories as sources, you can use this snippet: 52 | 53 | #+BEGIN_SRC emacs-lisp 54 | (load-library "find-lisp") 55 | (setq org-randomnote-candidates 56 | (find-lisp-find-files "~/Documents/3 Resources" "\.org$")) 57 | #+END_SRC 58 | 59 | This way ~org-randomnote~ will find any org file in that folder. 60 | 61 | However, be aware that you may see the warning ~org-randomnote: Wrong type argument: number-or-marker-p, nil~. This warning will crop up when ~org-randomnote~ brings up a file that doesn't have any actual Org headers (e.g. "* 1 Projects"). 62 | 63 | For org-randomnote's purposes, a "note" is considered a heading in an Org file. In this way, an org file is somewhat analogous to a notebook in Evernote, whereas the individual headings are notes. 64 | 65 | This is not necessarily intuitive or perfect, but it works well enough to begin with, especially since it can still find such a file randomly. 66 | -------------------------------------------------------------------------------- /org-randomnote.el: -------------------------------------------------------------------------------- 1 | ;;; org-randomnote.el --- Find a random note in your Org-Mode files 2 | 3 | ;; Copyright (C) 2017 Michael Fogleman 4 | 5 | ;; Author: Michael Fogleman 6 | ;; URL: http://github.com/mwfogleman/org-randomnote 7 | ;; Version: 0.1.0 8 | ;; Package-Requires: ((f "0.19.0") (dash "2.12.0") org) 9 | 10 | ;; This file is NOT part of GNU Emacs. 11 | 12 | ;;; License: 13 | 14 | ;; This program is free software; you can redistribute it and/or modify 15 | ;; it under the terms of the GNU General Public License as published by 16 | ;; the Free Software Foundation; either version 3, or (at your option) 17 | ;; any later version. 18 | 19 | ;; This program is distributed in the hope that it will be useful, 20 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | ;; GNU General Public License for more details. 23 | 24 | ;; You should have received a copy of the GNU General Public License 25 | ;; along with GNU Emacs; see the file COPYING. If not, write to the 26 | ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 27 | ;; Boston, MA 02110-1301, USA. 28 | 29 | ;;; Commentary: 30 | 31 | ;; This package implements the "Random Note" functionality popularized 32 | ;; by Tiago Forte with Evernote in Emacs Org-Mode. 33 | 34 | ;;; Code: 35 | 36 | (require 'dash) 37 | (require 'f) 38 | (require 'org) 39 | 40 | (defvar org-randomnote-candidates (org-agenda-files) 41 | "The files that org-randomnote will draw from in finding a random note. Defaults to `(org-agenda-files)'.") 42 | 43 | (defvar org-randomnote-open-behavior 'default 44 | "Configure the behavior that org-randomnote uses to open a random note. Set to `default' or `indirect-buffer'.") 45 | 46 | (defun org-randomnote--get-randomnote-candidates () 47 | (if (eq org-randomnote-candidates 'current-buffer) 48 | (list buffer-file-name) 49 | 50 | ;; Remove empty files from `org-randomnote-candidates'. 51 | (-remove 'f-empty? org-randomnote-candidates))) 52 | 53 | (defun org-randomnote--get-random-file () 54 | "Select a random file from `org-randomnote-candidates'." 55 | (seq-random-elt (org-randomnote--get-randomnote-candidates))) 56 | 57 | (defun org-randomnote--get-random-subtree (f match) 58 | "Get a random subtree satisfying Org match within an Org file F." 59 | (find-file f) 60 | (seq-random-elt (org-map-entries (lambda () (line-number-at-pos)) match 'file))) 61 | 62 | (defun org-randomnote--go-to-random-header (f match) 63 | "Given an Org file F, go to a random header satisfying Org match within that file." 64 | (org-goto-line (org-randomnote--get-random-subtree f match)) 65 | (outline-show-all) 66 | (recenter-top-bottom 0)) 67 | 68 | (defun org-randomnote--with-indirect-buffer (f match) 69 | "Given an Org file F, go to a random header satisfying Org match within that file." 70 | (org-goto-line (org-randomnote--get-random-subtree f match)) 71 | (org-tree-to-indirect-buffer) 72 | (switch-to-buffer (other-buffer))) 73 | 74 | ;;;###autoload 75 | (defun org-randomnote (&optional match) 76 | "Go to a random note satisfying Org match within a random Org file." 77 | (interactive) 78 | (let* ((f (org-randomnote--get-random-file)) 79 | (match (or match nil))) 80 | (cond ((eq org-randomnote-open-behavior 'default) (org-randomnote--go-to-random-header f match)) 81 | ((eq org-randomnote-open-behavior 'indirect-buffer) (org-randomnote--with-indirect-buffer f match))))) 82 | 83 | (provide 'org-randomnote) 84 | 85 | ;;; org-randomnote.el ends here 86 | --------------------------------------------------------------------------------