Include the POV field in the file-list hover tooltip
Header parsing now also lifts a `POV:` line (any heading level). The file-list tooltip combines it with the slug — "POV: <name>" then the slug synopsis — cached per file alongside the slug (HoverInfo) and read live from the buffer for the selected file. Adds a POV parse test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N9kRuP7JvXoUGdNNeg5ZSs
This commit is contained in:
@@ -29,6 +29,8 @@ pub struct Header {
|
||||
pub title: Option<String>,
|
||||
/// Value of the `# Slug:` line, if present and non-empty.
|
||||
pub slug: Option<String>,
|
||||
/// Value of the `POV:` line, if present and non-empty.
|
||||
pub pov: Option<String>,
|
||||
/// Word-count target from a `Word Count Target:` line, if present and parsable.
|
||||
pub goal: Option<WordGoal>,
|
||||
/// The prose body, with comments, the header block, and metadata lines removed.
|
||||
@@ -39,6 +41,7 @@ pub struct Header {
|
||||
enum Meta {
|
||||
Title,
|
||||
Slug,
|
||||
Pov,
|
||||
WordCount,
|
||||
}
|
||||
|
||||
@@ -105,6 +108,7 @@ fn meta_line(line: &str) -> Option<(Meta, String)> {
|
||||
for (key, meta) in [
|
||||
("title:", Meta::Title),
|
||||
("slug:", Meta::Slug),
|
||||
("pov:", Meta::Pov),
|
||||
("word count target:", Meta::WordCount),
|
||||
("word count goal:", Meta::WordCount),
|
||||
("word count:", Meta::WordCount),
|
||||
@@ -134,10 +138,12 @@ pub fn parse(markdown: &str, marker: &str) -> Header {
|
||||
|
||||
let mut title = None;
|
||||
let mut slug = None;
|
||||
let mut pov = None;
|
||||
let mut goal = None;
|
||||
let mut set = |meta: Meta, value: String| match meta {
|
||||
Meta::Title => title = Some(value),
|
||||
Meta::Slug => slug = Some(value),
|
||||
Meta::Pov => pov = Some(value),
|
||||
Meta::WordCount => goal = parse_goal(&value),
|
||||
};
|
||||
|
||||
@@ -173,6 +179,7 @@ pub fn parse(markdown: &str, marker: &str) -> Header {
|
||||
Header {
|
||||
title: title.filter(|s| !s.is_empty()),
|
||||
slug: slug.filter(|s| !s.is_empty()),
|
||||
pov: pov.filter(|s| !s.is_empty()),
|
||||
goal,
|
||||
body: body_lines.join("\n").trim().to_string(),
|
||||
}
|
||||
@@ -265,4 +272,15 @@ mod tests {
|
||||
let md = "# Title: Plain\n### Rough Draft:\n\nText.";
|
||||
assert_eq!(parse(md, MARKER).goal, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parses_pov_at_heading_level_two() {
|
||||
let md = "# Title: Bixby\n## POV: Bixby\n### Rough Draft:\n\nThe prose.";
|
||||
let h = parse(md, MARKER);
|
||||
assert_eq!(h.pov.as_deref(), Some("Bixby"));
|
||||
assert_eq!(h.body, "The prose.");
|
||||
// A prose line that merely starts with "POV" is not metadata.
|
||||
let md2 = "### Rough Draft:\n\nPOV of the crowd was tense.";
|
||||
assert_eq!(parse(md2, MARKER).pov, None);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user