diff options
Diffstat (limited to 'src/changes.rs')
-rw-r--r-- | src/changes.rs | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/src/changes.rs b/src/changes.rs index 5099364..986e9c4 100644 --- a/src/changes.rs +++ b/src/changes.rs @@ -1,3 +1,5 @@ +use std::path::PathBuf; + use rowan::NodeOrToken; use crate::pipeline::Change; @@ -174,3 +176,46 @@ fn next_indentation(node: &rnix::SyntaxNode) -> Option<usize> { None } } + +/// give line & column of a position marker in the given string +fn line_at_textpos(content: &str, pos: rowan::TextSize) -> Option<(usize, usize)> { + let pos: usize = pos.into(); + content + .split("\n") + .scan(0usize, |acc,line| { + let start = *acc; + let end = line.len() + 1 + start; + *acc = end; + Some((start, end)) + }) + .enumerate() + .find(|(_, (_, end))| *end > pos) + .map(|(line, (start, _))| (line + 1, pos + 1 - start)) +} + +pub fn format_pos(path: &PathBuf, content: &str, pos1: rowan::TextSize) -> String { + let (line1, col1) = line_at_textpos(content, pos1).unwrap(); + format!("{path:?}:{line1}:{col1}") +} + +pub fn format_range(path: &PathBuf, content: &str, range: rowan::TextRange) -> String { + let (line1, col1) = line_at_textpos(content, range.start()).unwrap(); + let (line2, col2) = line_at_textpos(content, range.end()).unwrap(); + format!("{}:{line1}:{col1}-{line2}:{col2}", path.to_string_lossy()) +} + +pub fn format_range_json(path: &PathBuf, content: &str, range: rowan::TextRange) -> serde_json::Value { + let (line1, col1) = line_at_textpos(content, range.start()).unwrap(); + let (line2, col2) = line_at_textpos(content, range.end()).unwrap(); + serde_json::json!({ + "file": path, + "start": { + "line": line1, + "column": col1 + }, + "end": { + "line": line2, + "column": col2 + } + }) +} |