Skip to content

auto-fill-mode messes :BACKLINKS: drawers #180

Description

@anuvyklack

Caution

This is generated by LLM, but I read it very carefully.

With auto-fill-mode enabled in Org buffers, org-node hard-wraps long backlink lines when writing a :BACKLINKS:{.verbatim} drawer, and the re-sort that immediately follows then reorders the two halves --- leaving the continuation stranded above the bullet it belongs to.

:BACKLINKS:
  real cost]]
- [[id:20260727T174609][The TLB, why four table reads per access is not the
:END:

Root cause

Both drawer writers terminate a line with newline rather than
(insert "\n"):

  • org-node-backlink.el:572-574 --- in org-node-backlink--fix-nearby-drawer, the to-add loop, unconditional.
  • org-node-backlink.el:726-730 --- in org-node-backlink--add-to-drawer, guarded by (unless (eolp) ...), so it only fires into a non-empty drawer.

newline is not a plain insert: it deliberately routes through self-insert-command so abbrev expansion and auto-fill run, even when called non-interactively from Lisp. Its own source carries a FIXME saying as much:

FIXME: For non-interactive uses, many calls actually just want (insert
"\n{=latex}"), so maybe we should do just that, so as to avoid the
risk of filling or running abbrevs unexpectedly.

So any backlink wider than fill-column gets hard-wrapped on insertion. The reordering comes from the re-sort that follows, which splits the drawer on newlines and so treats each physical line as an independent entry:

(let ((sorted-lines (sort (split-string (buffer-string) "\n" t)
                          org-node-backlink-drawer-sorter)))
  ...)

The default sorter org-node-backlink-id-blind-string-collate-lessp strips [[id:...]{.verbatim} and compares the remainder, so the orphan real cost]]{.verbatim} sorts ahead of The TLB, ...{.verbatim} and is hoisted above its own bullet.

Suggested patch

Replace (newline) with (insert "\n") at both sites. Nothing in a drawer-construction path wants abbrev expansion or auto-filling. Belt and braces would be to bind auto-fill-function to nil across both writers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions