1
0
Fork 0

[Feat] support line number & remove unused module (#91)

main
The Mist 2024-04-26 01:01:17 +08:00 committed by GitHub
parent ef08881e1a
commit 3b7dd6a3ad
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 149 additions and 83 deletions

View File

@ -2,6 +2,7 @@ use cached::proc_macro::cached;
use regex::Regex; use regex::Regex;
const MIN_WIDTH: f32 = 100.; const MIN_WIDTH: f32 = 100.;
pub const CHAR_WIDTH: f32 = 9.05;
fn min_width(width: f32) -> f32 { fn min_width(width: f32) -> f32 {
if width < MIN_WIDTH { if width < MIN_WIDTH {

View File

@ -1,7 +1,9 @@
pub mod background; pub mod background;
pub mod breadcrumbs; pub mod breadcrumbs;
pub mod code_block;
pub mod container; pub mod container;
pub mod editor; pub mod editor;
pub mod interface; pub mod interface;
pub mod line_number;
pub mod rect; pub mod rect;
pub mod watermark; pub mod watermark;

View File

@ -0,0 +1,29 @@
use crate::edges::margin::Margin;
use super::interface::{
component::Component,
style::{RawComponentStyle, Style},
};
pub struct CodeBlock {
children: Vec<Box<dyn Component>>,
}
impl Component for CodeBlock {
fn children(&self) -> &Vec<Box<dyn Component>> {
&self.children
}
fn style(&self) -> RawComponentStyle {
Style::default().margin(Margin {
top: 10.,
..Margin::default()
})
}
}
impl CodeBlock {
pub fn from_children(children: Vec<Box<dyn Component>>) -> CodeBlock {
CodeBlock { children }
}
}

View File

@ -1,11 +1,10 @@
use crate::{ use crate::{
code::{calc_wh, prepare_code}, code::{calc_wh, prepare_code, CHAR_WIDTH},
components::interface::{ components::interface::{
component::{Component, ComponentContext, RenderParams}, component::{Component, ComponentContext, RenderParams},
render_error, render_error,
style::{ComponentStyle, RawComponentStyle, Size, Style}, style::{ComponentStyle, RawComponentStyle, Size, Style},
}, },
edges::margin::Margin,
highlight::Highlight, highlight::Highlight,
text::FontRenderer, text::FontRenderer,
}; };
@ -23,14 +22,9 @@ impl Component for Code {
} }
fn style(&self) -> RawComponentStyle { fn style(&self) -> RawComponentStyle {
let (w, h) = calc_wh(&self.value, 9.05, self.line_height); let (w, h) = calc_wh(&self.value, CHAR_WIDTH, self.line_height);
Style::default() Style::default().size(Size::Num(w), Size::Num(h))
.size(Size::Num(w), Size::Num(h))
.margin(Margin {
top: 10.,
..Margin::default()
})
} }
fn draw_self( fn draw_self(

View File

@ -0,0 +1,99 @@
use super::interface::{
component::{Component, ComponentContext, RenderParams},
render_error,
style::{ComponentStyle, RawComponentStyle, Size, Style},
};
use crate::{code::CHAR_WIDTH, edges::margin::Margin, text::FontRenderer};
use cosmic_text::{Attrs, Color, Family};
const FONT_SIZE: f32 = 14.;
#[derive(Default)]
pub struct LineNumber {
children: Vec<Box<dyn Component>>,
line_height: f32,
render_condition: bool,
line_number_content: Vec<String>,
number_of_digit: usize,
}
impl Component for LineNumber {
fn render_condition(&self) -> bool {
return self.render_condition;
}
fn children(&self) -> &Vec<Box<dyn Component>> {
&self.children
}
fn style(&self) -> RawComponentStyle {
Style::default()
.size(
Size::Num(CHAR_WIDTH * self.number_of_digit as f32),
Size::Num(self.line_number_content.len() as f32 * self.line_height),
)
.margin(Margin {
right: 10.,
..Margin::default()
})
}
fn draw_self(
&self,
pixmap: &mut tiny_skia::Pixmap,
context: &ComponentContext,
render_params: &RenderParams,
style: &ComponentStyle,
) -> render_error::Result<()> {
FontRenderer::new(
FONT_SIZE,
self.line_height,
context.scale_factor,
&context.take_snapshot_params.fonts_folder,
)
.draw_text(
render_params.x,
render_params.y,
style.width,
style.height,
vec![(
&self.line_number_content.join("\n"),
Attrs::new()
.color(Color::rgb(73, 81, 98))
.family(Family::Name(&context.take_snapshot_params.code_font_family)),
)],
pixmap,
);
Ok(())
}
}
impl LineNumber {
pub fn new(content: &str, start_line_number: Option<usize>, line_height: f32) -> LineNumber {
match start_line_number {
None => LineNumber::default(),
Some(start_line_number) => {
let lines = content.split("\n").collect::<Vec<&str>>();
let max_line_number = lines.len() + start_line_number;
let number_of_digit = (max_line_number - 1).to_string().len();
LineNumber {
line_number_content: (start_line_number..max_line_number)
.map(|line_number| {
format!(
"{:>width$}",
line_number.to_string(),
width = number_of_digit
)
})
.collect::<Vec<String>>(),
number_of_digit,
children: vec![],
render_condition: true,
line_height,
}
}
}
}
}

View File

@ -26,6 +26,7 @@ pub struct TakeSnapshotParams {
pub file_path: String, pub file_path: String,
pub breadcrumbs_separator: String, pub breadcrumbs_separator: String,
pub has_breadcrumbs: bool, pub has_breadcrumbs: bool,
pub start_line_number: Option<usize>,
} }
impl FromObject for TakeSnapshotParams { impl FromObject for TakeSnapshotParams {

View File

@ -4,11 +4,13 @@ use tiny_skia::Pixmap;
use crate::components::background::Background; use crate::components::background::Background;
use crate::components::breadcrumbs::Breadcrumbs; use crate::components::breadcrumbs::Breadcrumbs;
use crate::components::code_block::CodeBlock;
use crate::components::container::Container; use crate::components::container::Container;
use crate::components::editor::code::Code; use crate::components::editor::code::Code;
use crate::components::editor::mac_title_bar::MacTitleBar; use crate::components::editor::mac_title_bar::MacTitleBar;
use crate::components::interface::component::ComponentContext; use crate::components::interface::component::ComponentContext;
use crate::components::interface::render_error; use crate::components::interface::render_error;
use crate::components::line_number::LineNumber;
use crate::components::rect::Rect; use crate::components::rect::Rect;
use crate::components::watermark::Watermark; use crate::components::watermark::Watermark;
use crate::config::TakeSnapshotParams; use crate::config::TakeSnapshotParams;
@ -33,7 +35,10 @@ pub fn take_snapshot(params: TakeSnapshotParams) -> render_error::Result<Pixmap>
params.breadcrumbs_separator, params.breadcrumbs_separator,
params.has_breadcrumbs, params.has_breadcrumbs,
)), )),
Box::new(Code::new(params.code, 20., 15.)), Box::new(CodeBlock::from_children(vec![
Box::new(LineNumber::new(&params.code, params.start_line_number, 20.)),
Box::new(Code::new(params.code, 20., 15.)),
])),
], ],
)), )),
Box::new(Watermark::new(params.watermark)), Box::new(Watermark::new(params.watermark)),

View File

@ -1,61 +0,0 @@
local logger = require("codesnap.utils.logger")
local static = require("codesnap.static")
local client = {
job_id = 0,
}
local cwd = static.cwd .. "/snap-server"
function client:connect()
return vim.fn.jobstart({
cwd .. "/target/release/snap-server",
}, {
cwd = cwd,
stderr_buffered = true,
rpc = true,
on_stderr = function(_, err)
vim.fn.jobstop(self.job_id)
logger.error(err)
end,
on_exit = function()
vim.fn.chanclose(self.job_id)
self.job_id = 0
end,
})
end
function client:init()
return self.job_id == 0 and client:connect() or self.job_id
end
function client:start()
self.job_id = client:init()
if self.job_id == 0 then
logger.error("cannot start rpc process")
return
end
if self.job_id == -1 then
logger.error("rpc process is not executable")
vim.fn.jobstop(self.job_id)
return
end
return self
end
function client:send(event, message)
vim.fn.rpcnotify(self.job_id, event, message)
end
function client:stop()
if self.job_id == 0 or self.job_id == -1 then
return
end
vim.fn.jobstop(self.job_id)
end
return client

View File

@ -27,6 +27,7 @@ end
function config_module.get_config(extension) function config_module.get_config(extension)
local code = visual_utils.get_selected_text() local code = visual_utils.get_selected_text()
local start_line_number = visual_utils.get_start_line_number()
if string_utils.is_str_empty(code) then if string_utils.is_str_empty(code) then
error("No code is selected", 0) error("No code is selected", 0)
@ -41,6 +42,7 @@ function config_module.get_config(extension)
themes_folder = assets_folder .. "/themes", themes_folder = assets_folder .. "/themes",
theme = "base16-onedark", theme = "base16-onedark",
file_path = static.config.has_breadcrumbs and path_utils.get_relative_path() or "", file_path = static.config.has_breadcrumbs and path_utils.get_relative_path() or "",
start_line_number = static.config.has_line_number and start_line_number or nil,
}, static.config) }, static.config)
config.save_path = parse_save_path(config.save_path) config.save_path = parse_save_path(config.save_path)

View File

@ -36,6 +36,7 @@ function main.save_snapshot(extension)
require("generator").save_snapshot(config) require("generator").save_snapshot(config)
vim.cmd("delmarks <>") vim.cmd("delmarks <>")
---@diagnostic disable-next-line: need-check-nil
vim.notify("Save snapshot in " .. config.save_path .. " successfully") vim.notify("Save snapshot in " .. config.save_path .. " successfully")
end end

View File

@ -10,6 +10,7 @@ return {
bg_theme = "default", bg_theme = "default",
breadcrumbs_separator = "/", breadcrumbs_separator = "/",
has_breadcrumbs = false, has_breadcrumbs = false,
has_line_number = false,
}, },
cwd = path_utils.back(path_utils.back(debug.getinfo(1, "S").source:sub(2):match("(.*[/\\])"))), cwd = path_utils.back(path_utils.back(debug.getinfo(1, "S").source:sub(2):match("(.*[/\\])"))),
preview_switch = true, preview_switch = true,

View File

@ -1,11 +0,0 @@
local logger = {}
function logger.log(level, message)
vim.api.nvim_notify("[" .. level .. "] CodeSnap: " .. tostring(vim.inspect(message)), vim.log.levels[level], {})
end
function logger.error(message)
logger.log("ERROR", message)
end
return logger

View File

@ -2,7 +2,6 @@ local visual_utils = {}
-- Get all the lines from "from" to "to" and return them as a single string -- Get all the lines from "from" to "to" and return them as a single string
-- If "from" and "to" are the same, return the line at "from" -- If "from" and "to" are the same, return the line at "from"
local function get_whole_lines(from, to) local function get_whole_lines(from, to)
local lines = {} local lines = {}
if from == to then if from == to then
@ -15,6 +14,10 @@ local function get_whole_lines(from, to)
return table.concat(lines, "\n") return table.concat(lines, "\n")
end end
function visual_utils.get_start_line_number()
return vim.fn.line("'<")
end
function visual_utils.get_selected_text() function visual_utils.get_selected_text()
local selected_text = vim.fn.getline("'<", "'>") local selected_text = vim.fn.getline("'<", "'>")