diff --git a/generator/src/code.rs b/generator/src/code.rs index 13baeb4..b40f2d2 100644 --- a/generator/src/code.rs +++ b/generator/src/code.rs @@ -1,3 +1,5 @@ +use regex::Regex; + const MIN_WIDTH: f32 = 100.; fn min_width(width: f32) -> f32 { @@ -9,7 +11,8 @@ fn min_width(width: f32) -> f32 { } pub fn calc_wh(text: &str, char_wdith: f32, line_height: f32) -> (f32, f32) { - let lines = text.lines(); + let trimmed_text = trim_space(text); + let lines = trimmed_text.lines(); let max_length_line = lines.clone().into_iter().fold("", |max_length_line, cur| { if cur.len() > max_length_line.len() { cur @@ -22,3 +25,25 @@ pub fn calc_wh(text: &str, char_wdith: f32, line_height: f32) -> (f32, f32) { (min_width(width), height) } + +pub fn trim_space(text: &str) -> String { + let lines = text.split("\n").collect::>(); + let first_line = lines.first().unwrap(); + let head_spaces = Regex::new(r"^(\s*)").unwrap().find(first_line); + + match head_spaces { + Some(head_spaces) => { + return lines + .into_iter() + .map(|line| { + Regex::new(format!("^{}", head_spaces.as_str()).as_ref()) + .unwrap() + .replace(line, "") + .to_string() + }) + .collect::>() + .join("\n"); + } + None => text.to_string(), + } +} diff --git a/generator/src/components.rs b/generator/src/components.rs index dd87c27..c14e6db 100644 --- a/generator/src/components.rs +++ b/generator/src/components.rs @@ -1,4 +1,5 @@ pub mod background; +pub mod breadcrumbs; pub mod container; pub mod editor; pub mod interface; diff --git a/generator/src/components/breadcrumbs.rs b/generator/src/components/breadcrumbs.rs new file mode 100644 index 0000000..e096dda --- /dev/null +++ b/generator/src/components/breadcrumbs.rs @@ -0,0 +1,89 @@ +use cosmic_text::{Attrs, Color, Family}; +use regex::Regex; + +use crate::{code::calc_wh, edges::margin::Margin, text::FontRenderer}; + +use super::interface::{ + component::Component, + style::{RawComponentStyle, Size}, +}; + +pub struct Breadcrumbs { + children: Vec>, + path: String, + line_height: f32, + has_breadcrumbs: bool, +} + +impl Component for Breadcrumbs { + fn children(&self) -> &Vec> { + &self.children + } + + fn style(&self) -> RawComponentStyle { + let style = RawComponentStyle::default(); + + if self.has_breadcrumbs { + let (w, h) = calc_wh(&self.path, 8., self.line_height); + + style.size(Size::Num(w), Size::Num(h)).margin(Margin { + top: 5., + ..Margin::default() + }) + } else { + style + } + } + + fn draw_self( + &self, + pixmap: &mut tiny_skia::Pixmap, + context: &super::interface::component::ComponentContext, + render_params: &super::interface::component::RenderParams, + style: &super::interface::style::ComponentStyle, + ) -> super::interface::render_error::Result<()> { + if self.has_breadcrumbs { + let attrs = Attrs::new() + .color(Color::rgb(128, 132, 139)) + .family(Family::Name(&context.take_snapshot_params.code_font_family)); + + FontRenderer::new( + 12., + self.line_height, + context.scale_factor, + &context.take_snapshot_params.fonts_folder, + ) + .draw_text( + render_params.x, + render_params.y, + style.width, + self.line_height, + vec![(&self.path, attrs)], + pixmap, + ); + } + + Ok(()) + } +} + +impl Breadcrumbs { + pub fn from_path( + path: String, + line_height: f32, + separator: String, + has_breadcrumbs: bool, + ) -> Breadcrumbs { + let path = Regex::new("/") + .unwrap() + .replace_all(&path, separator) + .to_string(); + + Breadcrumbs { + children: vec![], + path, + line_height, + has_breadcrumbs, + } + } +} diff --git a/generator/src/components/editor/code.rs b/generator/src/components/editor/code.rs index de258f5..04a5631 100644 --- a/generator/src/components/editor/code.rs +++ b/generator/src/components/editor/code.rs @@ -1,5 +1,5 @@ use crate::{ - code::calc_wh, + code::{calc_wh, trim_space}, components::interface::{ component::{Component, ComponentContext, RenderParams}, render_error, @@ -42,7 +42,7 @@ impl Component for Code { ) -> render_error::Result<()> { let params = &context.take_snapshot_params; let highlight = Highlight::new( - params.code.clone(), + self.value.clone(), params.code_font_family.clone(), params.language.clone(), params.extension.clone(), @@ -71,7 +71,7 @@ impl Component for Code { impl Code { pub fn new(value: String, line_height: f32, font_size: f32) -> Code { Code { - value, + value: trim_space(&value), line_height, font_size, children: vec![], diff --git a/generator/src/config.rs b/generator/src/config.rs index 58ce8cd..82c0048 100644 --- a/generator/src/config.rs +++ b/generator/src/config.rs @@ -19,6 +19,9 @@ pub struct TakeSnapshotParams { pub theme: String, pub bg_theme: String, pub bg_color: Option, + pub file_path: String, + pub breadcrumbs_separator: String, + pub has_breadcrumbs: bool, } impl FromObject for TakeSnapshotParams { diff --git a/generator/src/snapshot.rs b/generator/src/snapshot.rs index 3c984c4..1344e48 100644 --- a/generator/src/snapshot.rs +++ b/generator/src/snapshot.rs @@ -3,6 +3,7 @@ use std::sync::Arc; use tiny_skia::Pixmap; use crate::components::background::Background; +use crate::components::breadcrumbs::Breadcrumbs; use crate::components::container::Container; use crate::components::editor::code::Code; use crate::components::editor::mac_title_bar::MacTitleBar; @@ -26,6 +27,12 @@ pub fn take_snapshot(params: TakeSnapshotParams) -> render_error::Result 16., vec![ Box::new(MacTitleBar::from_radius(8.)), + Box::new(Breadcrumbs::from_path( + params.file_path, + 15., + params.breadcrumbs_separator, + params.has_breadcrumbs, + )), Box::new(Code::new(params.code, 20., 15.)), ], )), diff --git a/lua/codesnap/init.lua b/lua/codesnap/init.lua index a268db7..d11dd1b 100644 --- a/lua/codesnap/init.lua +++ b/lua/codesnap/init.lua @@ -3,6 +3,7 @@ local table_utils = require("codesnap.utils.table") local generator = require("generator") local string_utils = require("codesnap.utils.string") local visual_utils = require("codesnap.utils.visual") +local path_utils = require("codesnap.utils.path") local assets_folder = static.cwd .. "/assets" @@ -40,6 +41,7 @@ local function get_config() fonts_folder = assets_folder .. "/fonts", themes_folder = assets_folder .. "/themes", theme = "base16-onedark", + file_path = static.config.has_breadcrumbs and path_utils.get_relative_path() or "", }, static.config) end diff --git a/lua/codesnap/static.lua b/lua/codesnap/static.lua index d0137a0..518158e 100644 --- a/lua/codesnap/static.lua +++ b/lua/codesnap/static.lua @@ -8,6 +8,8 @@ return { watermark_font_family = "Pacifico", watermark = "CodeSnap.nvim", bg_theme = "default", + breadcrumbs_separator = "/", + has_breadcrumbs = false, }, cwd = path_utils.back(path_utils.back(debug.getinfo(1, "S").source:sub(2):match("(.*[/\\])"))), preview_switch = true, diff --git a/lua/codesnap/utils/path.lua b/lua/codesnap/utils/path.lua index 617bcb7..ebf4a54 100644 --- a/lua/codesnap/utils/path.lua +++ b/lua/codesnap/utils/path.lua @@ -1,3 +1,4 @@ +local string_utils = require("codesnap.utils.string") local path_utils = {} function path_utils.back(path) @@ -6,4 +7,11 @@ function path_utils.back(path) return parsed_path end +function path_utils.get_relative_path() + local full_file_path = vim.fn.expand("%:p") + local cwd = vim.fn.getcwd() + + return full_file_path:gsub(string_utils.escape(cwd), ""):sub(2) +end + return path_utils