Skip to content

Commit ac6a56f

Browse files
committed
feat: render fenced code blocks at 0.9x body size; persist+remap folds across file reload
1 parent ca17b7c commit ac6a56f

2 files changed

Lines changed: 39 additions & 2 deletions

File tree

src/core.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1652,8 +1652,16 @@ impl Editor {
16521652
/// Only parse/snapshot/diff work — no IO.
16531653
pub fn apply_reload(&mut self, content: String, base_text: Option<String>) {
16541654
if !self.state.buffer.content_eq(&content) {
1655+
// Persist folds across the reload: remap their offsets from the actual
1656+
// splice (external edits are usually a localized change), the same way a
1657+
// local edit does. `set_text` leaves `folded_headings` untouched, so without
1658+
// this the old offsets would land on the wrong lines in the new content.
1659+
let before = (!self.folded_headings.is_empty()).then(|| self.state.buffer.text());
16551660
let cursor_line = self.state.buffer.byte_to_line(self.state.selection.head);
16561661
self.set_text(&content);
1662+
if let Some(before) = before {
1663+
self.remap_folds(&before, &content);
1664+
}
16571665
let line = cursor_line.min(self.state.buffer.line_count().saturating_sub(1));
16581666
let offset = self.state.buffer.line_to_byte(line);
16591667
self.state.selection = Selection::new(offset, offset);
@@ -2533,6 +2541,24 @@ let code = target(); // fenced block line
25332541
);
25342542
}
25352543

2544+
#[test]
2545+
fn folds_persist_and_remap_across_reload() {
2546+
let mut e = Editor::new("# One\nbody\n## Two\nmore\n");
2547+
let two = e.text().find("## Two").unwrap();
2548+
e.toggle_fold(two);
2549+
assert!(e.folded_headings.contains(&two));
2550+
// An external edit prepends a line; the reload should shift the fold offset so it
2551+
// still lands on the (moved) heading rather than pointing at stale bytes.
2552+
let prefix = "intro line\n";
2553+
e.apply_reload(format!("{prefix}# One\nbody\n## Two\nmore\n"), None);
2554+
let two_after = e.text().find("## Two").unwrap();
2555+
assert_eq!(two_after, two + prefix.len());
2556+
assert!(
2557+
e.folded_headings.contains(&two_after),
2558+
"fold should remap to the heading's new offset after reload"
2559+
);
2560+
}
2561+
25362562
#[test]
25372563
fn find_replace_current_is_single_undo_step() {
25382564
let mut e = Editor::new("a a a\n");

src/render.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ pub struct LineRender {
121121
pub table: Option<TableLineRef>,
122122
}
123123

124+
/// Font-size multiplier for fenced code blocks — slightly smaller than body, matching
125+
/// how GitHub/most editors render code denser than prose.
126+
const CODE_BLOCK_SCALE: f32 = 0.9;
127+
124128
/// Font-size multiplier for a heading level (1 = largest). 0 = body text. A modular type
125129
/// scale on the Major Third ratio (1.25), anchored so H6 = body size (the floor — no
126130
/// heading is ever smaller than body) and each step up is 1.25× the last, giving large,
@@ -217,9 +221,16 @@ pub fn build_line_render(
217221
let line_end = line_start + line_text.len();
218222

219223
let heading_level = markers.heading_level().unwrap_or(0);
220-
let font_size = base_font_size * heading_scale(heading_level);
221-
let cursor_on_line = cursor_in(&range, cursor_offset);
222224
let in_code_block = markers.in_code_block || markers.is_fence();
225+
// Fenced code renders slightly smaller (GitHub-style) so a code block reads as a
226+
// denser, distinct block instead of competing with body prose. Headings and code are
227+
// mutually exclusive, so the two scales never combine.
228+
let font_size = if in_code_block {
229+
base_font_size * CODE_BLOCK_SCALE
230+
} else {
231+
base_font_size * heading_scale(heading_level)
232+
};
233+
let cursor_on_line = cursor_in(&range, cursor_offset);
223234

224235
// Grid table row: the cursor is off the whole table block, so this line hides its
225236
// raw pipe text and the draw path paints the cell grid. While the cursor is inside

0 commit comments

Comments
 (0)