Skip to content

Commit 1b50d9d

Browse files
authored
[Feat] add line number option (#33)
1 parent f357600 commit 1b50d9d

File tree

3 files changed

+74
-61
lines changed

3 files changed

+74
-61
lines changed

cli/src/code.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,25 @@ use std::{
77
use anyhow::bail;
88
use clap::CommandFactory;
99
use codesnap::{
10-
config::{Breadcrumbs, Code, CodeBuilder, HighlightLine},
10+
config::{Breadcrumbs, Code, CodeBuilder, HighlightLine, LineNumberBuilder},
1111
utils::clipboard::Clipboard,
1212
};
1313

14-
use crate::{
15-
range::{cut_code_snippet_by_range, prepare_range},
16-
CLI, STDIN_CODE_DEFAULT_CHAR,
17-
};
14+
use crate::{range::Range, CLI, STDIN_CODE_DEFAULT_CHAR};
1815

1916
pub fn create_code(cli: &CLI, config_code: Code) -> anyhow::Result<Code> {
20-
let code_snippet = cut_code_snippet_by_range(
21-
&get_code_snippet(cli)?,
22-
&cli.range
23-
.clone()
24-
.and_then(|range| Some(prepare_range(&range))),
25-
)?;
17+
let range = Range::from_opt_string(cli.range.clone())?;
18+
let code_snippet = range.cut_code_snippet(get_code_snippet(cli)?)?;
2619
let mut code_builder = CodeBuilder::from_code(config_code.clone());
2720
let mut code = code_builder.content(&code_snippet).build()?;
2821

22+
code.line_number = cli.has_line_number.then(|| {
23+
LineNumberBuilder::default()
24+
.start_number(range.0.parse::<u32>().unwrap_or(1))
25+
.color(cli.line_number_color.clone())
26+
.build()
27+
.unwrap()
28+
});
2929
code.theme = cli.code_theme.clone().unwrap_or(config_code.theme);
3030
code.font_family = cli
3131
.code_font_family

cli/src/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ struct CLI {
7777
#[arg(long)]
7878
has_breadcrumbs: bool,
7979

80+
#[arg(long)]
81+
has_line_number: bool,
82+
8083
/// Breadcrumbs separator is the character to separate the path in breadcrumbs
8184
/// Default is `/`
8285
#[arg(long)]

cli/src/range.rs

Lines changed: 60 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,67 +3,77 @@ use std::str::Lines;
33
use anyhow::bail;
44

55
const RANGE_SEPARATOR: &'static str = ":";
6-
const DEFAULT_RANGE: &'static str = "start:end";
6+
pub const DEFAULT_RANGE: &'static str = "start:end";
77

8-
fn parse_range_point(point: &str, lines: &Vec<&str>) -> anyhow::Result<usize> {
9-
let point = match point {
10-
"start" => 0,
11-
"end" => lines.len(),
12-
_ => point.parse::<usize>()?,
13-
};
8+
pub struct Range(pub String, pub String);
149

15-
Ok(point)
16-
}
10+
impl Range {
11+
// Prepare range string by following rules:
12+
//
13+
// If raw_range is equal to "n:", which means x:end
14+
// If raw_range is equal to ":n", which means start:n
15+
fn prepare_range(raw_range: &str) -> String {
16+
if raw_range.starts_with(RANGE_SEPARATOR) {
17+
format!("{}{}", "start", raw_range)
18+
} else if raw_range.ends_with(RANGE_SEPARATOR) {
19+
format!("{}{}", raw_range, "end")
20+
} else {
21+
raw_range.to_string()
22+
}
23+
}
24+
25+
pub fn from_opt_string(opt_str: Option<String>) -> anyhow::Result<Self> {
26+
Range::from_str(&opt_str.unwrap_or(String::from(DEFAULT_RANGE)))
27+
}
1728

18-
pub fn cut_code_snippet_by_range(
19-
code_snippet: &str,
20-
range: &Option<String>,
21-
) -> anyhow::Result<String> {
22-
let range = range.clone().unwrap_or(String::from(DEFAULT_RANGE));
23-
let range_points = range.split(RANGE_SEPARATOR).collect::<Vec<_>>();
29+
pub fn from_str(range_str: &str) -> anyhow::Result<Self> {
30+
let range = Range::prepare_range(range_str);
31+
let range_points = range.split(RANGE_SEPARATOR).collect::<Vec<_>>();
2432

25-
if range_points.len() != 2 {
26-
bail!("Invalid range format");
33+
if range_points.len() != 2 {
34+
bail!("Invalid range format");
35+
}
36+
37+
Ok(Range(
38+
range_points[0].to_string(),
39+
range_points[1].to_string(),
40+
))
2741
}
2842

29-
let code_snippet_lines = code_snippet.lines();
30-
let (start, end) = parse_range(&range_points, &code_snippet_lines)?;
31-
let code_snippet = code_snippet_lines
32-
.skip(start)
33-
.take(end - start)
34-
.collect::<Vec<&str>>()
35-
.join("\n");
43+
// 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)> {
45+
let Range(start, end) = self;
46+
let lines = code_snippet_lines.clone().collect::<Vec<&str>>();
47+
let start = parse_range_point(&start, &lines)?;
48+
let end = parse_range_point(&end, &lines)?;
49+
let points = if start > end {
50+
(end, start)
51+
} else {
52+
(start, end)
53+
};
3654

37-
Ok(code_snippet)
38-
}
55+
Ok(points)
56+
}
3957

40-
// Prepare range string by following rules:
41-
//
42-
// If raw_range is equal to "n:", which means x:end
43-
// If raw_range is equal to ":n", which means start:n
44-
pub fn prepare_range(raw_range: &str) -> String {
45-
if raw_range.starts_with(RANGE_SEPARATOR) {
46-
format!("{}{}", "start", raw_range)
47-
} else if raw_range.ends_with(RANGE_SEPARATOR) {
48-
format!("{}{}", raw_range, "end")
49-
} else {
50-
raw_range.to_string()
58+
pub fn cut_code_snippet(&self, code_snippet: String) -> anyhow::Result<String> {
59+
let code_snippet_lines = code_snippet.lines();
60+
let (start, end) = self.parse_range(&code_snippet_lines)?;
61+
let code_snippet = code_snippet_lines
62+
.skip(start)
63+
.take(end - start)
64+
.collect::<Vec<&str>>()
65+
.join("\n");
66+
67+
Ok(code_snippet)
5168
}
5269
}
5370

54-
// Parse "start" to 0, "end" to lines.len(), and other values to usize
55-
pub fn parse_range(
56-
range_points: &Vec<&str>,
57-
code_snippet_lines: &Lines,
58-
) -> anyhow::Result<(usize, usize)> {
59-
let lines = code_snippet_lines.clone().collect::<Vec<&str>>();
60-
let start = parse_range_point(range_points[0], &lines)?;
61-
let end = parse_range_point(range_points[1], &lines)?;
62-
let points = if start > end {
63-
(end, start)
64-
} else {
65-
(start, end)
71+
fn parse_range_point(point: &str, lines: &Vec<&str>) -> anyhow::Result<usize> {
72+
let point = match point {
73+
"start" => 1,
74+
"end" => lines.len(),
75+
_ => point.parse::<usize>()?,
6676
};
6777

68-
Ok(points)
78+
Ok(point)
6979
}

0 commit comments

Comments
 (0)