Skip to content

docs: Break lines at meaning boundaries - #2903

Open
krlmlr wants to merge 4 commits into
claude/badge-harmonizationfrom
claude/sembr
Open

docs: Break lines at meaning boundaries#2903
krlmlr wants to merge 4 commits into
claude/badge-harmonizationfrom
claude/sembr

Conversation

@krlmlr

@krlmlr krlmlr commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

Reformatting only, no wording changes. Prose in the roxygen and inline comments under R/, four vignettes and README.md now breaks at sentence and clause boundaries rather than wrapping to a fixed width — the convention AGENTS.md already asks for ("Use line breaks after each sentence", "Keep each sentence on its own line in roxygen2 comments"). This brings the rest of the package in line with it.

This is the largest package in a fleet-wide pass: ~22,000 roxygen lines.

The three commits

  1. Break lines at meaning boundaries — the bulk reflow.
  2. Start every broken sentence on its own line — once a sentence has to span lines, it and its neighbour each start at a line start.
  3. Break the joined sentences apart — see below.

How it was done

By script rather than by hand, because hand-editing 22,000 lines cannot be made consistent or reviewable. Each reflowable block is joined and re-split at sentence boundaries, then at clause boundaries — comma, semicolon, colon, else a subordinating conjunction — only where a sentence would exceed 140 columns.

Blocks already conforming are emitted verbatim: 17 of 84 in-scope R/*.R files come out byte-identical, and within changed files any unit that is already one sentence per line is passed through untouched. The pass is idempotent — re-running it on the result changes nothing.

The double-space gap, and the third commit

Two spaces between sentences render literally in Rd2txt(), and a line break swallows one of them: commonmark discards the whitespace a break stands for. So the first two commits could not break at such a gap, and left 93 single lines of up to 407 columns — including a Bonacich-centrality paragraph and a plot.igraph() paragraph that no break could touch at all.

The third commit breaks those 93 lines apart at 99 sentence gaps, plus 15 further clause breaks so nothing it creates exceeds 140 columns. The longest roxygen line in the package drops from 407 to 344 columns, and lines over 140 from 196 to 149.

The patched roxygen2 is a separate pull request

Restoring the gap that a break now swallows needs a patched roxygen2. That is a separate decision, and it is #2906, stacked on top of this chain, so it can be taken or left on its own.

Without it the rendered help moves in exactly one way: where a sentence pair separated by two spaces was split across lines, the gap narrows to a single space. tools::Rd2txt() over the 633 topics this branch regenerates finds 80 of them differing, and every difference is whitespace and nothing else — in arpack, to be solved. Possible values becomes to be solved. Possible values. Restoring those 80 is what #2906 does.

man/ is not edited by hand here. CI roxygenises and commits the regenerated .Rd files itself, so whichever roxygen2 is installed at that point is what produces them; they arrive on this branch as an automated commit rather than in the hand-written diff.

Rebased on current main

main moved under this branch, mostly through #2868 (the dots documentation) and the new constructor_spec, layout_spec and igraph_opt topics. Generated files were resolved by regenerating, never by hand. The nine hand-written R/ conflicts were all the same shape — main rewrote a @param \dots or added a @seealso sentence, this branch reflowed the old text — and were resolved by taking main's wording and breaking it at sentence boundaries. Each resolved file was checked word-for-word against main's version with comment markers stripped and whitespace collapsed, so nothing was reworded, lost or added. The prose main brought in is reflowed to the same convention.

Verification

  • Zero non-comment lines changed under R/. Confirmed by filtering the diff.
  • tools::Rd2txt() over all 665 topics, comparing the base of this branch with its tip as documented by the patched roxygen2 of ci: Document with a patched roxygen2 that keeps the sentence gap #2906: 529 topics change, every difference is sentence spacing, and no topic loses a gap.
  • Word-level identity of every file touched by a conflict resolution: comment markers stripped, whitespace collapsed, compared against main.
  • Roxygenising twice is byte-stable over six consecutive runs, apart from the pre-existing drift below.
  • Pandoc HTML of both vignettes, both articles and README.md — byte-identical before and after.
  • air format . — no further changes. Rscript tools/check-id-casing.R — 0 violations. Every R/ file parses.

Pre-existing man/ drift, not from this PR

Regenerating on a pristine checkout renames the C-library links in seven topics — cliques, cluster_leading_eigen, isomorphisms, leading.eigenvector.community, maximal.cliques, simple_cycles and subgraph_isomorphisms — dropping the *_callback C functions the committed man/ points at. This branch edits no man/ by hand, so it neither introduces nor fixes that, but the drift is real and is someone's to resolve separately. It is the same drift as the motifs_randesu_callback_closure() one, which main has since fixed.

Left alone

  • The 32 generated files — the 28 aaa-*.R, cpp11.R, three import-standalone-*.R — and the # BEGIN/END GENERATED ARG_HANDLE regions inside hand-written files.
  • @examples, @usage and other non-prose tags; \preformatted{}, \tabular{}, code fences, markdown tables, and the structural indentation of \describe{}, \itemize{}, \enumerate{}.
  • Bibliography entries under @references. A . there separates a title from a journal, not two sentences, so six of them keep the gap mid-line.
  • The \enumerate{} block in the spectrum topic. Its items are inconsistent — some \item followed by a space, some by a line break, which Rd2txt() renders as one space versus two — so no reflow leaves the rendering identical.
  • The # " lines in R/components.R — typo'd roxygen (# " rather than #') inside a block, not comments.
  • README.md's allcontributors HTML table; only the ~6 prose lines above it changed.
  • 149 lines still over 140 columns, each a single sentence with no meaning-preserving break — long URLs, parenthetical-only clauses, and a few very long clauses.

r-lib/here#195 is the reference PR for this pass, reviewed by hand before the rest were run.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WWhverMTZZKgEpUuTK117m

@github-actions

Copy link
Copy Markdown
Contributor

This is how benchmark results would change (along with a 95% confidence interval in relative change) if 308cf79 is merged into claude/badge-harmonization:

  • ✔️as_adjacency_matrix: 242ms -> 241ms [-0.75%, +0.34%]
  • ✔️as_biadjacency_matrix: 255ms -> 256ms [-0.38%, +0.76%]
  • ✔️as_data_frame_both: 259ms -> 260ms [-0.23%, +0.52%]
  • ✔️as_long_data_frame: 208ms -> 207ms [-0.77%, +0.32%]
  • 🚀es_attr_filter: 244ms -> 242ms [-1.1%, -0.34%]
  • ✔️graph_from_adjacency_matrix: 271ms -> 271ms [-0.09%, +0.61%]
  • ✔️graph_from_data_frame: 274ms -> 276ms [-0.09%, +0.93%]
  • ✔️vs_attr_filter: 327ms -> 330ms [-0.06%, +1.89%]
  • ✔️vs_by_name: 308ms -> 309ms [-0.33%, +0.64%]
    Further explanation regarding interpretation and methodology can be found in the documentation.

@github-actions

Copy link
Copy Markdown
Contributor

This is how benchmark results would change (along with a 95% confidence interval in relative change) if 9bb18cf is merged into claude/badge-harmonization:

  • ✔️as_adjacency_matrix: 178ms -> 179ms [-0.18%, +1.38%]
  • ✔️as_biadjacency_matrix: 198ms -> 197ms [-0.97%, +0.2%]
  • 🚀as_data_frame_both: 201ms -> 199ms [-1.42%, -0.07%]
  • ✔️as_long_data_frame: 160ms -> 160ms [-0.4%, +0.92%]
  • ✔️es_attr_filter: 188ms -> 188ms [-0.71%, +0.58%]
  • ✔️graph_from_adjacency_matrix: 215ms -> 215ms [-0.5%, +0.71%]
  • ✔️graph_from_data_frame: 215ms -> 216ms [-0.57%, +1.56%]
  • ✔️vs_attr_filter: 230ms -> 229ms [-0.51%, +0.34%]
  • ✔️vs_by_name: 209ms -> 212ms [-0.87%, +3.64%]
    Further explanation regarding interpretation and methodology can be found in the documentation.

@github-actions

Copy link
Copy Markdown
Contributor

This is how benchmark results would change (along with a 95% confidence interval in relative change) if 4b46f7b is merged into claude/badge-harmonization:

  • ✔️as_adjacency_matrix: 176ms -> 176ms [-0.73%, +0.11%]
  • ✔️as_biadjacency_matrix: 196ms -> 196ms [-0.81%, +0.4%]
  • ✔️as_data_frame_both: 199ms -> 198ms [-0.78%, +0.16%]
  • ✔️as_long_data_frame: 161ms -> 161ms [-1.78%, +1.67%]
  • ❗🐌es_attr_filter: 186ms -> 188ms [+0.06%, +1.23%]
  • ✔️graph_from_adjacency_matrix: 213ms -> 213ms [-0.63%, +0.14%]
  • ✔️graph_from_data_frame: 216ms -> 214ms [-2.82%, +1.29%]
  • ✔️vs_attr_filter: 227ms -> 227ms [-0.35%, +0.52%]
  • ✔️vs_by_name: 208ms -> 208ms [-0.29%, +0.59%]
    Further explanation regarding interpretation and methodology can be found in the documentation.

@github-actions

Copy link
Copy Markdown
Contributor

This is how benchmark results would change (along with a 95% confidence interval in relative change) if 0a0aa9e is merged into claude/badge-harmonization:

  • ✔️as_adjacency_matrix: 242ms -> 244ms [-0.51%, +1.6%]
  • ❗🐌as_biadjacency_matrix: 258ms -> 260ms [+0.07%, +1.02%]
  • ✔️as_data_frame_both: 262ms -> 261ms [-0.87%, +0.43%]
  • ✔️as_long_data_frame: 207ms -> 207ms [-0.61%, +0.3%]
  • 🚀es_attr_filter: 246ms -> 243ms [-1.53%, -0.6%]
  • ✔️graph_from_adjacency_matrix: 273ms -> 273ms [-0.43%, +1.01%]
  • ✔️graph_from_data_frame: 272ms -> 273ms [-0.69%, +1.07%]
  • ✔️vs_attr_filter: 331ms -> 331ms [-0.74%, +0.52%]
  • ✔️vs_by_name: 310ms -> 311ms [-0.23%, +0.98%]
    Further explanation regarding interpretation and methodology can be found in the documentation.

@github-actions

Copy link
Copy Markdown
Contributor

This is how benchmark results would change (along with a 95% confidence interval in relative change) if 1abfa9d is merged into claude/badge-harmonization:

  • ✔️as_adjacency_matrix: 219ms -> 217ms [-1.84%, +0.61%]
  • ✔️as_biadjacency_matrix: 224ms -> 226ms [-1.19%, +2.99%]
  • ✔️as_data_frame_both: 209ms -> 209ms [-1.78%, +1.1%]
  • 🚀as_long_data_frame: 173ms -> 172ms [-1.14%, -0.06%]
  • ✔️es_attr_filter: 216ms -> 217ms [-0.68%, +1.16%]
  • ✔️graph_from_adjacency_matrix: 259ms -> 259ms [-1.03%, +0.85%]
  • ✔️graph_from_data_frame: 233ms -> 234ms [-0.37%, +1.56%]
  • ✔️vs_attr_filter: 221ms -> 221ms [-0.89%, +1.54%]
  • ✔️vs_by_name: 189ms -> 188ms [-1.96%, +1.21%]
    Further explanation regarding interpretation and methodology can be found in the documentation.

@github-actions

Copy link
Copy Markdown
Contributor

This is how benchmark results would change (along with a 95% confidence interval in relative change) if 3b92d5c is merged into claude/badge-harmonization:

  • ✔️as_adjacency_matrix: 246ms -> 248ms [-0.38%, +1.4%]
  • ✔️as_biadjacency_matrix: 260ms -> 262ms [-0.24%, +1.73%]
  • ✔️as_data_frame_both: 266ms -> 266ms [-0.76%, +0.84%]
  • ✔️as_long_data_frame: 213ms -> 212ms [-1.22%, +0.5%]
  • 🚀es_attr_filter: 247ms -> 246ms [-1.11%, -0.14%]
  • ✔️graph_from_adjacency_matrix: 277ms -> 275ms [-1.76%, +0.28%]
  • ✔️graph_from_data_frame: 283ms -> 282ms [-1.83%, +0.85%]
  • ✔️vs_attr_filter: 333ms -> 334ms [-0.73%, +1.19%]
  • ✔️vs_by_name: 318ms -> 315ms [-2.01%, +0.16%]
    Further explanation regarding interpretation and methodology can be found in the documentation.

@krlmlr
krlmlr added this pull request to stack #2907 September 13, 2026 21:25
krlmlr and others added 3 commits September 13, 2026 23:26
Reformatting only, no wording changes: prose in README.md, the
vignettes and the roxygen and inline comments under R/ now breaks at
sentence and clause boundaries rather than wrapping to a fixed width.

The payoff is sentence-level diffs. A reworded sentence touches one
line instead of reflowing the paragraph around it, so review sees the
change and not the rewrap.

man/*.Rd is regenerated because roxygen2 passes source line breaks
through to the .Rd. The rendered help is byte-identical -- checked with
tools::Rd2txt() over every topic -- as is the rendered README.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WWhverMTZZKgEpUuTK117m
Follow-up to the semantic line break pass, reformatting only.
Where a sentence has to be broken across lines,
that sentence and the sentence after it now each start at the beginning of a line,
so a reworded sentence touches its own lines instead of reflowing its neighbours.

Some sentence pairs are separated by two spaces, which `Rd2txt()` renders literally.
Breaking there would drop a space from the rendered help,
so those pairs are joined onto one long line instead of being broken elsewhere.
That is why a few lines now exceed the usual width.

Left alone: citation lists under `@references`, the GPL headers,
the aligned input/output comment in `R/epi.R`,
the `\enumerate{}` block in `R/centrality.R`
whose items render differently depending on whether `\item` is followed by a space or a line break,
and paragraphs where honouring the rule would need a single line of more than 300 characters.

man/*.Rd is regenerated because roxygen2 passes source line breaks through to the .Rd.
The rendered help is byte-identical -- checked with tools::Rd2txt() over all 662 topics.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WWhverMTZZKgEpUuTK117m
The long single-line roxygen paragraphs existed only to protect a sentence
gap: two spaces between sentences that a line break used to swallow, because
commonmark discards the whitespace a break stands for and Rd2txt then rendered
the gap as one space. Joining was the only way to keep it.

The joins come out, including the 26 places the earlier pass had to leave
alone because joining them would have produced lines of 1440 and 973
characters.

The spectrum topic in R/centrality.R keeps its \enumerate{} block as is: its
items are inconsistent, some \item followed by a space and some by a line
break, which Rd2txt renders as one space versus two, so no reflow leaves the
rendering identical.

man/ is left to CI, which regenerates it from these sources.

A line break which follows the end of a sentence currently renders as one space rather than two.
Restoring that gap needs a patched roxygen2, which is a separate decision and a separate pull request,
so it is deliberately not part of this change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WWhverMTZZKgEpUuTK117m
@github-actions

Copy link
Copy Markdown
Contributor

This is how benchmark results would change (along with a 95% confidence interval in relative change) if 126e3cf is merged into claude/badge-harmonization:

  • ✔️as_adjacency_matrix: 182ms -> 184ms [-1.95%, +4.26%]
  • ✔️as_biadjacency_matrix: 203ms -> 202ms [-1.48%, +0.18%]
  • ✔️as_data_frame_both: 203ms -> 205ms [-0.78%, +1.81%]
  • ✔️as_long_data_frame: 162ms -> 163ms [-0.57%, +0.89%]
  • ✔️es_attr_filter: 191ms -> 190ms [-0.89%, +0.06%]
  • ✔️graph_from_adjacency_matrix: 217ms -> 217ms [-0.89%, +0.45%]
  • ✔️graph_from_data_frame: 218ms -> 218ms [-1.06%, +0.34%]
  • ✔️vs_attr_filter: 235ms -> 235ms [-0.9%, +0.54%]
  • ✔️vs_by_name: 215ms -> 215ms [-0.31%, +0.77%]
    Further explanation regarding interpretation and methodology can be found in the documentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant