[Feat] support line number & remove unused module (#91)
parent
ef08881e1a
commit
3b7dd6a3ad
|
@ -2,6 +2,7 @@ use cached::proc_macro::cached;
|
|||
use regex::Regex;
|
||||
|
||||
const MIN_WIDTH: f32 = 100.;
|
||||
pub const CHAR_WIDTH: f32 = 9.05;
|
||||
|
||||
fn min_width(width: f32) -> f32 {
|
||||
if width < MIN_WIDTH {
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
pub mod background;
|
||||
pub mod breadcrumbs;
|
||||
pub mod code_block;
|
||||
pub mod container;
|
||||
pub mod editor;
|
||||
pub mod interface;
|
||||
pub mod line_number;
|
||||
pub mod rect;
|
||||
pub mod watermark;
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
}
|
|
@ -1,11 +1,10 @@
|
|||
use crate::{
|
||||
code::{calc_wh, prepare_code},
|
||||
code::{calc_wh, prepare_code, CHAR_WIDTH},
|
||||
components::interface::{
|
||||
component::{Component, ComponentContext, RenderParams},
|
||||
render_error,
|
||||
style::{ComponentStyle, RawComponentStyle, Size, Style},
|
||||
},
|
||||
edges::margin::Margin,
|
||||
highlight::Highlight,
|
||||
text::FontRenderer,
|
||||
};
|
||||
|
@ -23,14 +22,9 @@ impl Component for Code {
|
|||
}
|
||||
|
||||
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()
|
||||
.size(Size::Num(w), Size::Num(h))
|
||||
.margin(Margin {
|
||||
top: 10.,
|
||||
..Margin::default()
|
||||
})
|
||||
Style::default().size(Size::Num(w), Size::Num(h))
|
||||
}
|
||||
|
||||
fn draw_self(
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,6 +26,7 @@ pub struct TakeSnapshotParams {
|
|||
pub file_path: String,
|
||||
pub breadcrumbs_separator: String,
|
||||
pub has_breadcrumbs: bool,
|
||||
pub start_line_number: Option<usize>,
|
||||
}
|
||||
|
||||
impl FromObject for TakeSnapshotParams {
|
||||
|
|
|
@ -4,11 +4,13 @@ use tiny_skia::Pixmap;
|
|||
|
||||
use crate::components::background::Background;
|
||||
use crate::components::breadcrumbs::Breadcrumbs;
|
||||
use crate::components::code_block::CodeBlock;
|
||||
use crate::components::container::Container;
|
||||
use crate::components::editor::code::Code;
|
||||
use crate::components::editor::mac_title_bar::MacTitleBar;
|
||||
use crate::components::interface::component::ComponentContext;
|
||||
use crate::components::interface::render_error;
|
||||
use crate::components::line_number::LineNumber;
|
||||
use crate::components::rect::Rect;
|
||||
use crate::components::watermark::Watermark;
|
||||
use crate::config::TakeSnapshotParams;
|
||||
|
@ -33,7 +35,10 @@ pub fn take_snapshot(params: TakeSnapshotParams) -> render_error::Result<Pixmap>
|
|||
params.breadcrumbs_separator,
|
||||
params.has_breadcrumbs,
|
||||
)),
|
||||
Box::new(Code::new(params.code, 20., 15.)),
|
||||
Box::new(CodeBlock::from_children(vec![
|
||||
Box::new(LineNumber::new(¶ms.code, params.start_line_number, 20.)),
|
||||
Box::new(Code::new(params.code, 20., 15.)),
|
||||
])),
|
||||
],
|
||||
)),
|
||||
Box::new(Watermark::new(params.watermark)),
|
||||
|
|
|
@ -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
|
|
@ -27,6 +27,7 @@ end
|
|||
|
||||
function config_module.get_config(extension)
|
||||
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
|
||||
error("No code is selected", 0)
|
||||
|
@ -41,6 +42,7 @@ function config_module.get_config(extension)
|
|||
themes_folder = assets_folder .. "/themes",
|
||||
theme = "base16-onedark",
|
||||
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)
|
||||
|
||||
config.save_path = parse_save_path(config.save_path)
|
||||
|
|
|
@ -36,6 +36,7 @@ function main.save_snapshot(extension)
|
|||
|
||||
require("generator").save_snapshot(config)
|
||||
vim.cmd("delmarks <>")
|
||||
---@diagnostic disable-next-line: need-check-nil
|
||||
vim.notify("Save snapshot in " .. config.save_path .. " successfully")
|
||||
end
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ return {
|
|||
bg_theme = "default",
|
||||
breadcrumbs_separator = "/",
|
||||
has_breadcrumbs = false,
|
||||
has_line_number = false,
|
||||
},
|
||||
cwd = path_utils.back(path_utils.back(debug.getinfo(1, "S").source:sub(2):match("(.*[/\\])"))),
|
||||
preview_switch = true,
|
||||
|
|
|
@ -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
|
|
@ -2,7 +2,6 @@ local visual_utils = {}
|
|||
|
||||
-- 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"
|
||||
|
||||
local function get_whole_lines(from, to)
|
||||
local lines = {}
|
||||
if from == to then
|
||||
|
@ -15,6 +14,10 @@ local function get_whole_lines(from, to)
|
|||
return table.concat(lines, "\n")
|
||||
end
|
||||
|
||||
function visual_utils.get_start_line_number()
|
||||
return vim.fn.line("'<")
|
||||
end
|
||||
|
||||
function visual_utils.get_selected_text()
|
||||
local selected_text = vim.fn.getline("'<", "'>")
|
||||
|
||||
|
|
Loading…
Reference in New Issue