Documentation

Commentary

A lightweight annotation system for Emacs that allows you to add
persistent notes to any text file without modifying the original
content.  Enhanced with threading, collaboration, and org-mode
integration.  Requires Emacs 28.1+ (which bundles `transient').

Quick Start (use-package):

  (use-package simply-annotate
    :bind-keymap ("C-c a" . simply-annotate-command-map)
    :hook (find-file . simply-annotate-mode))

  (with-eval-after-load 'simply-annotate
    (add-hook 'dired-mode-hook #'simply-annotate-dired-mode))

Quick Start (require):

  (require 'simply-annotate)
  (global-set-key (kbd "C-c a") simply-annotate-command-map)
  (add-hook 'find-file-hook #'simply-annotate-mode)
  (add-hook 'dired-mode-hook #'simply-annotate-dired-mode)

All commands live in `simply-annotate-command-map', which you bind
to a prefix key of your choice.  With C-c a as the prefix:

1. Open any file
2. Select text and press C-c a j to create your first annotation
3. Navigate with the command prefix then `n` (next) and `p` (previous)

Keymap Configuration:

`simply-annotate-mode-map' is intentionally minimal and does not
install global `M-n`/`M-p` bindings.  All other commands are in
`simply-annotate-command-map':

  ;; Recommended: C-c a prefix (defers loading until first use)
  :bind-keymap ("C-c a" . simply-annotate-command-map)

  ;; Alternative: M-s prefix (replaces Emacs search-map)
  ;; Requires :demand t with global-set-key in :config
  ;; Do NOT use :bind-keymap with M-s (see docstring for details)
  ;; Call `simply-annotate-inherit-search-map' to keep the default
  ;; M-s bindings (occur, isearch-forward-symbol-at-point, etc.)
  ;; working via keymap inheritance.
  :demand t
  :config
  (global-set-key (kbd "M-s") simply-annotate-command-map)
  (simply-annotate-inherit-search-map)

Two features reduce prefix-typing for repeated commands:

- Transient menu: <prefix> ? (`simply-annotate-menu') opens a
  discoverable dispatcher; navigation and display toggles stay open
  so you can repeat them without re-opening the menu.
- `repeat_mode' (Emacs 28.1+): enable it with M-x repeat-mode (or
  (repeat-mode 1) in your init).  After one navigation/display
  command you can continue with the bare keys n p ' / [ ] g -- see
  `simply-annotate-repeat-map'.

Threading & Collaboration:

All keybindings below use <prefix> to denote your chosen prefix
(e.g. C-c a j means press C-c a then j).

* Replies
- Press <prefix> r to add a reply to any annotation
- Creates threaded conversations for code reviews

* Status Management
- Press <prefix> s to set status (open, in-progress, resolved, closed)
- Press <prefix> p to set priority (low, normal, high, critical)
- Press <prefix> t to add tags for organization
- Press <prefix> d to toggle hiding of done/closed threads; customise
  `simply-annotate-hide-done-statuses' (e.g. '("resolved" "closed")) and
  `simply-annotate-hide-done-style' (`full' or `indicator')
- Press <prefix> c to collapse/expand the inline annotation thread at
  point (requires inline display to be on via <prefix> /)

* Author Management
- Configure team members: (setq simply-annotate-author-list '("John" "Jane" "Bob"))
- Set prompting behavior: (setq simply-annotate-prompt-for-author 'threads-only)
- Press <prefix> a to change annotation author

* Editing
- Press <prefix> e to edit the current annotation
- Edit in a sexp form and then C-c C-c to save
- Any data field can be edited

* Org-mode Integration
- Press <prefix> o to export annotations to org-mode files
- Each thread becomes a TODO item with replies as sub-entries

Configuration Examples:

;; Single user (default)
(setq simply-annotate-prompt-for-author nil)

;; Team collaboration
(setq simply-annotate-author-list '("John Doe" "Jane Smith" "Bob Wilson"))
(setq simply-annotate-prompt-for-author 'threads-only)
(setq simply-annotate-remember-author-per-file t)

Inline Pointer Styles:

When inline display is enabled, a pointer connects the annotation
box to the annotated text.  Customise via
`simply-annotate-inline-pointer-after' (box below text) and
`simply-annotate-inline-pointer-above' (box above text).  Strings
can be multiline (use \n).  Set to nil to disable.

;; Simple arrows (default)
(setq simply-annotate-inline-pointer-after "▴")
(setq simply-annotate-inline-pointer-above "▾")

;; Larger triangles
(setq simply-annotate-inline-pointer-after "▲")
(setq simply-annotate-inline-pointer-above "▼")

;; Tall stems
(setq simply-annotate-inline-pointer-after "  ║")
(setq simply-annotate-inline-pointer-above "  ║")

;; Speech bubble tails
(setq simply-annotate-inline-pointer-after " ╰┐")
(setq simply-annotate-inline-pointer-above " ╰┐")

;; L-bracket connectors
(setq simply-annotate-inline-pointer-after "│\n╰─")
(setq simply-annotate-inline-pointer-above "╭─\n│")

(setq simply-annotate-inline-pointer-after "│\n╰──▸")
(setq simply-annotate-inline-pointer-above "╭──▸\n│")

;; Heavy L-bracket
(setq simply-annotate-inline-pointer-after "┃\n┗━▶")
(setq simply-annotate-inline-pointer-above "┏━▶\n┃")

;; Decorative single char
(setq simply-annotate-inline-pointer-after "●")
(setq simply-annotate-inline-pointer-above "●")

(setq simply-annotate-inline-pointer-after "◆")
(setq simply-annotate-inline-pointer-above "◆")

(setq simply-annotate-inline-pointer-after "✦")
(setq simply-annotate-inline-pointer-above "✦")

(setq simply-annotate-inline-pointer-after "⟡")
(setq simply-annotate-inline-pointer-above "⟡")

;; Minimal / subtle
(setq simply-annotate-inline-pointer-after "·")
(setq simply-annotate-inline-pointer-above "·")

(setq simply-annotate-inline-pointer-after "┊")
(setq simply-annotate-inline-pointer-above "┊")

(setq simply-annotate-inline-pointer-after "╷")
(setq simply-annotate-inline-pointer-above "╵")

;; Bracket pairs
(setq simply-annotate-inline-pointer-after "╰─┤")
(setq simply-annotate-inline-pointer-above "╭─┤")

;; Fancy multiline
(setq simply-annotate-inline-pointer-after "│\n│\n╰──▸")
(setq simply-annotate-inline-pointer-above "╭──▸\n│\n│")

(setq simply-annotate-inline-pointer-after "┃\n┃\n┗━━▶")
(setq simply-annotate-inline-pointer-above "┏━━▶\n┃\n┃")

Project-Aware Annotations:

By default, annotations are stored in a single global database.
Set `simply-annotate-database-strategy' to use per-project databases
that can be committed alongside your code:

;; Store annotations at the project root (.simply-annotations.el)
(setq simply-annotate-database-strategy 'project)

;; Or merge project and global databases (project wins on conflicts)
(setq simply-annotate-database-strategy 'both)

Project-scoped commands (require project.el):
- <prefix> P   show annotations for the current project (org listing)
- <prefix> C-t show annotations for the current project (sortable table)
- <prefix> f   jump to annotated file
- <prefix> A   cross-project overview of every project with annotations
               (sortable table with per-status counts).  Discovers both
               global-db entries and per-project `.simply-annotations.el'
               files via `project-known-project-roots'.  From the table,
               RET/L/K drill into the project's table/org/kanban view.

Dired-aware narrowing: when the four project commands above are
invoked from a `dired' buffer that lives under a project
subdirectory, they automatically narrow to that subdirectory --
useful for slicing large projects without any explicit selection
UI.  Prefix arguments escape this:

  no prefix  dired-aware project view (auto-narrow if applicable)
  C-u        whole project, ignoring any dired auto-narrow
  C-u C-u    every annotated file in the database (jump-to-file
             and `simply-annotate-show-project'); for the table and
             kanban this behaves the same as C-u

In the kanban buffer, a narrowed board can be widened with `d'
(clear directory filter) without leaving the buffer.  The currently
active directory is shown at the front of the kanban header line.

To migrate existing global annotations into a project database:
  M-x simply-annotate-migrate-to-project

Requires

Dependencies

Consumers

Reverse Dependencies

No reverse dependencies recorded.