Skip to content

Commit 3adfe18

Browse files
authored
[Feat] add --highlight-range option (#35)
1 parent 88f0bd4 commit 3adfe18

File tree

3 files changed

+57
-26
lines changed

3 files changed

+57
-26
lines changed

cli/src/code.rs

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ use crate::{range::Range, CLI, STDIN_CODE_DEFAULT_CHAR};
1515

1616
pub fn create_code(cli: &CLI, config_code: Code) -> anyhow::Result<Code> {
1717
let range = Range::from_opt_string(cli.range.clone())?;
18-
let code_snippet = range.cut_code_snippet(get_code_snippet(cli)?)?;
18+
let code_snippet = get_code_snippet(cli)?;
19+
let parsed_range = range.parse_range(&code_snippet)?;
20+
let parsed_code_snippet = parsed_range.cut_code_snippet(&code_snippet)?;
1921
let mut code_builder = CodeBuilder::from_code(config_code.clone());
20-
let mut code = code_builder.content(&code_snippet).build()?;
22+
let mut code = code_builder.content(&parsed_code_snippet).build()?;
2123

2224
code.line_number = cli.has_line_number.then(|| {
2325
LineNumberBuilder::default()
24-
.start_number(range.0.parse::<u32>().unwrap_or(1))
26+
.start_number(parsed_range.0 as u32)
2527
.color(cli.line_number_color.clone())
2628
.build()
2729
.unwrap()
@@ -34,22 +36,38 @@ pub fn create_code(cli: &CLI, config_code: Code) -> anyhow::Result<Code> {
3436
code.file_path = cli.from_file.clone().or(config_code.file_path);
3537
code.language = cli.language.clone().or(config_code.language);
3638
code.breadcrumbs = create_breadcrumbs(&cli).or(config_code.breadcrumbs);
37-
code.highlight_lines = create_highlight_lines(&cli)?;
39+
code.highlight_lines = create_highlight_lines(&cli, &code_snippet)?;
3840

3941
Ok(code)
4042
}
4143

42-
fn create_highlight_lines(cli: &CLI) -> Result<Vec<HighlightLine>, serde_json::Error> {
43-
match cli.highlight_lines {
44-
Some(ref highlight_lines) => serde_json::from_str::<Vec<HighlightLine>>(highlight_lines),
45-
None => Ok(vec![]),
44+
fn create_highlight_lines(cli: &CLI, code_snippet: &str) -> anyhow::Result<Vec<HighlightLine>> {
45+
if let Some(ref raw_highlight_lines) = cli.raw_highlight_lines {
46+
let highlight_lines = serde_json::from_str::<Vec<HighlightLine>>(raw_highlight_lines)?;
47+
48+
return Ok(highlight_lines);
4649
}
50+
51+
let highlight_lines = match cli.highlight_range {
52+
Some(ref highlight_range) => {
53+
let Range(start, end) = Range::from_str(&highlight_range)?.parse_range(code_snippet)?;
54+
55+
vec![HighlightLine::Range(
56+
start as u32,
57+
end as u32,
58+
cli.highlight_range_color.clone(),
59+
)]
60+
}
61+
None => vec![],
62+
};
63+
64+
Ok(highlight_lines)
4765
}
4866

4967
fn create_breadcrumbs(cli: &CLI) -> Option<Breadcrumbs> {
5068
cli.has_breadcrumbs.then(|| Breadcrumbs {
5169
separator: cli.breadcrumbs_separator.clone(),
52-
font_family: cli.breadcrumbs_font_family.clone(),
70+
font_family: Some(cli.breadcrumbs_font_family.clone()),
5371
color: cli
5472
.breadcrumbs_color
5573
.clone()

cli/src/main.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ struct CLI {
8686
breadcrumbs_separator: Option<String>,
8787

8888
/// Breadcrumbs font family
89-
#[arg(long)]
90-
breadcrumbs_font_family: Option<String>,
89+
#[arg(long, default_value = "CaskaydiaCove Nerd Font")]
90+
breadcrumbs_font_family: String,
9191

9292
/// Breadcrumbs font color
9393
#[arg(long)]
@@ -101,6 +101,15 @@ struct CLI {
101101
#[arg(long, default_value = "#495162")]
102102
line_number_color: String,
103103

104+
/// Convenient version of `--raw-highlight-lines` option, you can set the highlight range
105+
/// with a simple syntax, for example, highlight the 3rd to 5th lines:
106+
/// 3:5
107+
#[arg(long)]
108+
highlight_range: Option<String>,
109+
110+
#[arg(long, default_value = "#ffffff10")]
111+
highlight_range_color: String,
112+
104113
/// CodeSnap allows users to highlight multiple lines with custom highlight color in the code snippet
105114
/// The content of highlight_lines is JSON string, for example highlight the first line and the
106115
/// 3rd to 5th lines:
@@ -110,7 +119,7 @@ struct CLI {
110119
/// ]"
111120
///
112121
#[arg(long)]
113-
highlight_lines: Option<String>,
122+
raw_highlight_lines: Option<String>,
114123

115124
/// Set the language of the code snippet, If you using the `file` option, CodeSnap will
116125
/// automatically detect the language from the file extension.

cli/src/range.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ use anyhow::bail;
55
const RANGE_SEPARATOR: &'static str = ":";
66
pub const DEFAULT_RANGE: &'static str = "start:end";
77

8-
pub struct Range(pub String, pub String);
8+
pub struct Range<T>(pub T, pub T);
99

10-
impl Range {
10+
impl Range<String> {
1111
// Prepare range string by following rules:
1212
//
1313
// If raw_range is equal to "n:", which means x:end
@@ -30,20 +30,22 @@ impl Range {
3030
let range = Range::prepare_range(range_str);
3131
let range_points = range.split(RANGE_SEPARATOR).collect::<Vec<_>>();
3232

33-
if range_points.len() != 2 {
33+
// When range is in format "start:end", the length of range_points is 2
34+
// When range is in format "line_number", the length of range_points is 1
35+
if range_points.len() != 2 && range_points.len() != 1 {
3436
bail!("Invalid range format");
3537
}
3638

37-
Ok(Range(
38-
range_points[0].to_string(),
39-
range_points[1].to_string(),
40-
))
39+
let start = range_points[0].to_string();
40+
let end = range_points.get(1).unwrap_or(&start.as_str()).to_string();
41+
42+
Ok(Range(start, end))
4143
}
4244

4345
// Parse "start" to 0, "end" to lines.len(), and other values to usize
44-
fn parse_range(&self, code_snippet_lines: &Lines) -> anyhow::Result<(usize, usize)> {
46+
pub fn parse_range(&self, code_snippet: &str) -> anyhow::Result<Range<usize>> {
4547
let Range(start, end) = self;
46-
let lines = code_snippet_lines.clone().collect::<Vec<&str>>();
48+
let lines = code_snippet.lines().clone().collect::<Vec<&str>>();
4749
let start = parse_range_point(&start, &lines)?;
4850
let end = parse_range_point(&end, &lines)?;
4951
let points = if start > end {
@@ -52,15 +54,17 @@ impl Range {
5254
(start, end)
5355
};
5456

55-
Ok(points)
57+
Ok(Range(points.0, points.1))
5658
}
59+
}
5760

58-
pub fn cut_code_snippet(&self, code_snippet: String) -> anyhow::Result<String> {
61+
impl Range<usize> {
62+
pub fn cut_code_snippet(&self, code_snippet: &str) -> anyhow::Result<String> {
63+
let Range(start, end) = self;
5964
let code_snippet_lines = code_snippet.lines();
60-
let (start, end) = self.parse_range(&code_snippet_lines)?;
6165
let code_snippet = code_snippet_lines
62-
.skip(start)
63-
.take(end - start)
66+
.skip(start - 1)
67+
.take((end + 1) - start)
6468
.collect::<Vec<&str>>()
6569
.join("\n");
6670

0 commit comments

Comments
 (0)