Ren 連: A tiny Emacs library for note-taking that lets you use plain-text hyperlinks that work in different modes and across directories.
fix(so): Windows expands regexp "/\\." (dotfiles) to "/" (any file)
fix: remove ren-specific function call
docs: spell check on comments and docstrings


browse  log 



You can also use your local clone with git send-email.

I realize that this package is mentioned in Emacs news for 2024-04-22. I appreciate this.

At this stage, I would like to take things slowly and I don't think I have written enough documentation to get you started easily. I use it everyday and it works great for my own note-taking workflow, but I am still tweaking things a lot (because I like it this way). You are welcome to take a peak at what I am doing and try to see what the code does, but at this stage you may be in for a struggle.

Here is a very quick run down to help you get a glimpse of what Ren might do.

;; Assuming you installed `ren` subdirectory under `~/src`
;; All you need is ren.el.

(use-package ren
  :load-path ("~/src/ren")
  :hook emacs-startup)
  1. After evaluating this, enable ren-mode. It is a global minor mode. You should also see a message saying ren-files created in your user-emacs-directory. This is a list of files Ren tracks. Don't worry about it for now. It should be empty initially. It will have some entries when you quit Emacs. It should only contain Org, Markdown, or plain text files (but not program source files) by default. You don't have to do anything with the ren-files file. It is edited automatically like savehist.

  2. Start creating your notes in text-mode, org-mode, or markdown-mode (any major mode derived from text-mode). I believe you'd need minimum two files before you notice what Ren may do. Enter one or two same words in both files. Once you have done this, visit either of them, put your cursor on the word that appear in both files, and call xref-find-definitions (M-. by default) or xref-find-references (M-?, by default). I find M-. easier to press. You should see Xref showing the result of Grep. The more you have files with the same word, the exciting it gets.

This is it for now. I hope this helps you have a glimpse.

#Ren 連

Ren is part of my tiny-emacs-packages project.

Ren is a tiny Emacs library designed to make our note-taking easier by adding plain-text hyperlinks to our notes and documents. You can turn a date (eg "2024-02-25"), a wiki-style link (eg "[[note-taking]]"), or any single word into an "identifier" (ID) that works as a hyperlink. With Ren, you can use commands like xref-find-definitions and xref-find-references to find where these IDs are mentioned across your files (ie backlinks) even if they're in different folders and projects. Ren works with any plain-text file types like .txt, .md, and .org.

Under the hood, Ren is a collection of glue code and configuration, built on top of Emacs built-in libraries. It serves as a backend for the Xref (Cross-reference) library, adapting it to work with plain-text notes and document files instead of programming source files.

Identifiers (IDs) are defined using regular expressions (regexps), which are recognized by the thingatpoint.el (Thing-at-Point) library. Ren uses these IDs to interface with Xref to find definitions and references in files located in different directories. Ren also integrates with the built-in FFAP (Find File At Point) library to find a file associated with an ID at the cursor's position ("at point").

Ren 連 leverages the xref-find-references command to search where the terms are used. When it is used standalone, the xref-find-definitions command also does exactly the same as xref-find-references and does not search the definitions. For this, use my other tiny library, Ten 典, together. Ten helps you have a list of definitions of terms and connects with xref-find-definitions to search the definitions of terms. Ren and Ten complement with each other for this combined use.

Configuration may look like this:

(use-package ren
  :load-path ("~/src/ren/")
  :hook emacs-startup
  ;; Set files and directories to be searched. I set it to the entire
  ;; user directory of ~/ to `ren-files-and-directories'. Use
  ;; `ren-file-extensions' and `ren-exclude-regexps' to narrow down the
  ;; search scope. This gives me about 5,000 files to search with no
  ;; performance issue with my 8-old Lenovo Thinkpad T460 (16GB memory).
  ;; A quick benchmark is available: test/ren-benchmark.org. Adjust
  ;; these as you see fit.
  (ren-files-and-directories (list "~/"))
  (ren-exclude-regexps (list "/\\." "/node_modules" "/temp" "/tmp"))
  (ren-file-extensions '("org" "md" "txt" "kotl"))
  (ren-enabled-modes '(text-mode kotl-mode))
  ;; Optional. you can use `consult-xref' to display the Xref results.
  ;; Note this is not a setting specifict to Ren. It will affect Xref in
  ;; general including major modes for programming languages.
  (xref-show-xrefs-function 'consult-xref)
  (xref-show-definitions-function 'consult-xref)

  ;; Optional. The following are to get Ren to work with my other
  ;; library, Ten for searching definitions
  (ren-xref-use-etags-backend-in-this-mode 'ten-mode)
  (ren-id-at-point-function 'ten-id-at-point)
  ;; Make grep search case-insensitive for Ren
  (push (grep-case-insensitive
         . "xargs -0 grep <C> --null --ignore-case -snHE -e <R>")
  (setq ren-xref-search-program 'grep-case-insensitive)

  ;; Optional. you can configure Xref to skip the promt for completion
  ;; in `xref-find-references'. Note this is a general configuration for
  ;; Xref and not specific to Ren, including major modes for programming
  ;; language.
  (add-to-list 'xref-prompt-for-identifier #'xref-find-references :append))

Figure 1. consult-xref previews the list of files that contain string "note-taking". More than 10K files searched with grep across different directories with using xref, which takes less than a second.

Figure 2. ffap finds and suggests the file name for the ID 2020-03-31T123856 in the markdown wiki-link.

#Alternative command to find references

An alternative to Xref, you can use Consult to find references. This command uses consult-ripgrep instead of xref-find-references. Both are great. xref to me is simpler, and somewhat faster in my use, but consult can give you more flexibility in the regexp.

(defun ren-refernces-find ()
  "Find references for term at point.
This is an alternative for `xref-find-references' with using
  (let ((id (or (ren-id-at-point) (thing-at-point 'word))))
    (if (featurep 'consult)
        (consult-ripgrep (ren-files)
                         (when id (regexp-quote id)))
      (xref-find-references id))))