Skip to content

Commit

Permalink
[Perf] refactor highlight lines module & add relative highlight range…
Browse files Browse the repository at this point in the history
… argument (#48)

* [Perf] refactor highlight lines module

* [Feat] add relative highlight range argument
  • Loading branch information
mistricky authored Dec 22, 2024
1 parent 499773f commit 9b53f22
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 47 deletions.
33 changes: 20 additions & 13 deletions cli/src/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,7 @@ use codesnap::{
utils::clipboard::Clipboard,
};

use crate::{
highlight::{create_highlight_lines_by_opt_range, create_highlight_lines_by_ranges},
range::Range,
CLI, STDIN_CODE_DEFAULT_CHAR,
};
use crate::{highlight::HighlightLineRange, range::Range, CLI, STDIN_CODE_DEFAULT_CHAR};

pub fn create_code(cli: &CLI, config_code: Code) -> anyhow::Result<Code> {
let range = Range::from_opt_string(cli.range.clone())?;
Expand All @@ -40,27 +36,38 @@ pub fn create_code(cli: &CLI, config_code: Code) -> anyhow::Result<Code> {
code.file_path = cli.from_file.clone().or(config_code.file_path);
code.language = cli.language.clone().or(config_code.language);
code.breadcrumbs = create_breadcrumbs(&cli).or(config_code.breadcrumbs);
code.highlight_lines = create_highlight_lines(&cli, &code_snippet)?;
code.highlight_lines = create_highlight_lines(&cli, parsed_range, &code_snippet)?;

Ok(code)
}

fn create_highlight_lines(cli: &CLI, code_snippet: &str) -> anyhow::Result<Vec<HighlightLine>> {
fn create_highlight_lines(
cli: &CLI,
code_snippet_range: Range<usize>,
code_snippet: &str,
) -> anyhow::Result<Vec<HighlightLine>> {
if let Some(ref raw_highlight_lines) = cli.raw_highlight_lines {
let highlight_lines = serde_json::from_str::<Vec<HighlightLine>>(raw_highlight_lines)?;

return Ok(highlight_lines);
}

let highlight_lines = create_highlight_lines_by_opt_range(
&cli.highlight_range,
&cli.highlight_range_color,
let highlight_range = HighlightLineRange::from(
code_snippet_range,
code_snippet,
cli.relative_highlight_range,
)?;
let delete_highlight_lines =
create_highlight_lines_by_ranges(&cli.delete_line, &cli.delete_line_color, code_snippet)?;
let highlight_lines = cli
.highlight_range
.clone()
.and_then(|range| {
Some(highlight_range.create_highlight_lines(&range, &cli.highlight_range_color))
})
.unwrap_or(Ok(vec![]))?;
let delete_highlight_lines = highlight_range
.create_multiple_highlight_lines(&cli.delete_line, &cli.delete_line_color)?;
let new_highlight_lines =
create_highlight_lines_by_ranges(&cli.add_line, &cli.add_line_color, code_snippet)?;
highlight_range.create_multiple_highlight_lines(&cli.add_line, &cli.add_line_color)?;

Ok([highlight_lines, delete_highlight_lines, new_highlight_lines].concat())
}
Expand Down
127 changes: 93 additions & 34 deletions cli/src/highlight.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,102 @@
use anyhow::bail;
use codesnap::config::HighlightLine;

use crate::range::Range;

pub fn create_highlight_lines_by_range(
range: &str,
highlight_color: &str,
code_snippet: &str,
) -> anyhow::Result<Vec<HighlightLine>> {
let Range(start, end) = Range::from_str(&range)?.parse_range(code_snippet)?;

Ok(vec![HighlightLine::Range(
start as u32,
end as u32,
highlight_color.to_string(),
)])
pub struct HighlightLineRange {
code_snippet_range: Range<usize>,
code_snippet: String,
is_relative_highlight_range: bool,
}

pub fn create_highlight_lines_by_opt_range(
range: &Option<String>,
highlight_color: &str,
code_snippet: &str,
) -> anyhow::Result<Vec<HighlightLine>> {
match range {
Some(ref range) => create_highlight_lines_by_range(range, highlight_color, code_snippet),
None => Ok(vec![]),
impl HighlightLineRange {
pub fn from(
code_snippet_range: Range<usize>,
code_snippet: &str,
is_relative_highlight_range: bool,
) -> anyhow::Result<Self> {
Ok(HighlightLineRange {
code_snippet_range,
code_snippet: code_snippet.to_string(),
is_relative_highlight_range,
})
}
}

pub fn create_highlight_lines_by_ranges(
ranges: &Vec<String>,
highlight_color: &str,
code_snippet: &str,
) -> anyhow::Result<Vec<HighlightLine>> {
ranges.iter().try_fold(vec![], |mut acc, range| {
acc.extend(create_highlight_lines_by_range(
range,
highlight_color,
code_snippet,
)?);
Ok(acc)
})
fn get_absolute_highlight_range(
&self,
Range(start, end): Range<usize>,
) -> anyhow::Result<(usize, usize)> {
// let Range(start, end) = Range::from_str(&raw_range)?.parse_range(&self.code_snippet)?;
let Range(code_snippet_start, code_snippet_end) = self.code_snippet_range;
let offset_start = code_snippet_start - 1;

if start < code_snippet_start {
bail!(
"The highlight start range should be greater than or equal to {}",
code_snippet_start
);
}

if end > code_snippet_end {
bail!(
"The highlight end range should be less than or equal to {}",
code_snippet_end
);
}

// Users may specify a range to generate snapshot from a part of the whole code snippet,
// however the highlight range line number is start from already sliced code snippet
// so we need to known the start range to calculate the correct highlight range line number
let start = start - offset_start;
let end = end - offset_start;

Ok((start, end))
}

fn get_relative_highlight_range(
&self,
Range(start, end): Range<usize>,
) -> anyhow::Result<(usize, usize)> {
let Range(code_snippet_start, code_snippet_end) = self.code_snippet_range;
let code_snippet_range_size = code_snippet_end - code_snippet_start;

if end > code_snippet_range_size + 1 {
bail!(
"The highlight end range should be less than or equal to {}",
code_snippet_range_size
);
}

Ok((start, end))
}

pub fn create_highlight_lines(
&self,
raw_range: &str,
highlight_color: &str,
) -> anyhow::Result<Vec<HighlightLine>> {
let Range(start, end) = Range::from_str(&raw_range)?.parse_range(&self.code_snippet)?;
let (start, end) = if self.is_relative_highlight_range {
self.get_relative_highlight_range(Range(start, end))
} else {
self.get_absolute_highlight_range(Range(start, end))
}?;

Ok(vec![HighlightLine::Range(
start as u32,
end as u32,
highlight_color.to_string(),
)])
}

pub fn create_multiple_highlight_lines(
&self,
raw_ranges: &Vec<String>,
highlight_color: &str,
) -> anyhow::Result<Vec<HighlightLine>> {
raw_ranges.iter().try_fold(vec![], |mut acc, range| {
acc.extend(self.create_highlight_lines(range, highlight_color)?);
Ok(acc)
})
}
}
3 changes: 3 additions & 0 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ struct CLI {
#[arg(long)]
highlight_range: Option<String>,

#[arg(long)]
relative_highlight_range: bool,

/// Highlight color for the highlighted code lines
#[arg(long, default_value = "#ffffff10")]
highlight_range_color: String,
Expand Down
1 change: 1 addition & 0 deletions cli/src/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use anyhow::bail;
const RANGE_SEPARATOR: &'static str = ":";
pub const DEFAULT_RANGE: &'static str = "start:end";

#[derive(Debug)]
pub struct Range<T>(pub T, pub T);

impl Range<String> {
Expand Down

0 comments on commit 9b53f22

Please sign in to comment.