forked from mirror/codesnap.nvim
[Feat] support for take code snapshot in ASCII art format ^ ^ (#114)
* [Refactor] separate calc_wh_with_min_width from calc_wh * [Feat] support take code snapshot as ascii art * [Fix] incorrect line number * [Feat] remove unused loggermain
parent
8f03a0795b
commit
b3e3c23146
|
@ -12,9 +12,13 @@ fn min_width(width: f32) -> f32 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Because the code block is input by users, we need to calculate the width and height
|
pub fn calc_max_line_number_length(code_length: usize, start_line_number: usize) -> usize {
|
||||||
// to make sure render the width and height of the "editor" shape correctly
|
let max_line_number = code_length + start_line_number;
|
||||||
#[cached(key = "String", convert = r#"{ format!("{}", text) }"#)]
|
|
||||||
|
// If code length is 1, the max_line_number will equal to start_line_number
|
||||||
|
(max_line_number - 1).to_string().len()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn calc_wh(text: &str, char_wdith: f32, line_height: f32) -> (f32, f32) {
|
pub fn calc_wh(text: &str, char_wdith: f32, line_height: f32) -> (f32, f32) {
|
||||||
let trimmed_text = prepare_code(text);
|
let trimmed_text = prepare_code(text);
|
||||||
let lines = trimmed_text.lines();
|
let lines = trimmed_text.lines();
|
||||||
|
@ -28,6 +32,15 @@ pub fn calc_wh(text: &str, char_wdith: f32, line_height: f32) -> (f32, f32) {
|
||||||
let width = max_length_line.len() as f32 * char_wdith;
|
let width = max_length_line.len() as f32 * char_wdith;
|
||||||
let height = lines.collect::<Vec<&str>>().len() as f32 * line_height;
|
let height = lines.collect::<Vec<&str>>().len() as f32 * line_height;
|
||||||
|
|
||||||
|
(width, height)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Because the code block is input by users, we need to calculate the width and height
|
||||||
|
// to make sure render the width and height of the "editor" shape correctly
|
||||||
|
#[cached(key = "String", convert = r#"{ format!("{}", text) }"#)]
|
||||||
|
pub fn calc_wh_with_min_width(text: &str, char_wdith: f32, line_height: f32) -> (f32, f32) {
|
||||||
|
let (width, height) = calc_wh(text, char_wdith, line_height);
|
||||||
|
|
||||||
(min_width(width), height)
|
(min_width(width), height)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use cosmic_text::{Attrs, Color, Family};
|
use cosmic_text::{Attrs, Color, Family};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
use crate::{code::calc_wh, edges::margin::Margin, text::FontRenderer};
|
use crate::{code::calc_wh_with_min_width, edges::margin::Margin, text::FontRenderer};
|
||||||
|
|
||||||
use super::interface::{
|
use super::interface::{
|
||||||
component::Component,
|
component::Component,
|
||||||
|
@ -24,7 +24,7 @@ impl Component for Breadcrumbs {
|
||||||
let style = RawComponentStyle::default();
|
let style = RawComponentStyle::default();
|
||||||
|
|
||||||
if self.has_breadcrumbs {
|
if self.has_breadcrumbs {
|
||||||
let (w, h) = calc_wh(&self.path, 8., self.line_height);
|
let (w, h) = calc_wh_with_min_width(&self.path, 8., self.line_height);
|
||||||
|
|
||||||
style.size(Size::Num(w), Size::Num(h)).margin(Margin {
|
style.size(Size::Num(w), Size::Num(h)).margin(Margin {
|
||||||
top: 5.,
|
top: 5.,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
code::{calc_wh, prepare_code, CHAR_WIDTH},
|
code::{calc_wh_with_min_width, prepare_code, CHAR_WIDTH},
|
||||||
components::interface::{
|
components::interface::{
|
||||||
component::{Component, ComponentContext, RenderParams},
|
component::{Component, ComponentContext, RenderParams},
|
||||||
render_error,
|
render_error,
|
||||||
|
@ -22,7 +22,7 @@ impl Component for Code {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style(&self) -> RawComponentStyle {
|
fn style(&self) -> RawComponentStyle {
|
||||||
let (w, h) = calc_wh(&self.value, CHAR_WIDTH, self.line_height);
|
let (w, h) = calc_wh_with_min_width(&self.value, CHAR_WIDTH, self.line_height);
|
||||||
|
|
||||||
Style::default().size(Size::Num(w), Size::Num(h))
|
Style::default().size(Size::Num(w), Size::Num(h))
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
use std::cmp::max;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
code::{calc_max_line_number_length, calc_wh},
|
||||||
|
config::TakeSnapshotParams,
|
||||||
|
};
|
||||||
|
use arboard::Clipboard;
|
||||||
|
use nvim_oxi::Result;
|
||||||
|
|
||||||
|
const SPACE_BOTH_SIDE: usize = 2;
|
||||||
|
|
||||||
|
fn optional(component: String, is_view: bool) -> String {
|
||||||
|
if is_view {
|
||||||
|
component
|
||||||
|
} else {
|
||||||
|
"".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn copy_ascii(params: TakeSnapshotParams) -> Result<()> {
|
||||||
|
let (width, height) = calc_wh(¶ms.code, 1., 1.);
|
||||||
|
let calc_line_number_width =
|
||||||
|
|start_line_number: usize| calc_max_line_number_length(height as usize, start_line_number);
|
||||||
|
let frame_width = max(width as usize, params.file_path.len()) + SPACE_BOTH_SIDE;
|
||||||
|
let frame_width = match params.start_line_number {
|
||||||
|
Some(start_line_number) => {
|
||||||
|
frame_width + SPACE_BOTH_SIDE + calc_line_number_width(start_line_number)
|
||||||
|
}
|
||||||
|
None => frame_width,
|
||||||
|
};
|
||||||
|
let line = format!("│{}│\n", "─".repeat(frame_width));
|
||||||
|
let frame_width_with_content = frame_width - 1;
|
||||||
|
let top_frame = format!("╭{}╮\n", "─".repeat(frame_width));
|
||||||
|
let bottom_frame = format!("╰{}╯", "─".repeat(frame_width));
|
||||||
|
let code = params
|
||||||
|
.code
|
||||||
|
.lines()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, line)| {
|
||||||
|
format!(
|
||||||
|
"│ {:1$} │\n",
|
||||||
|
match params.start_line_number {
|
||||||
|
Some(start_line_number) => format!(
|
||||||
|
"{:1$} {line}",
|
||||||
|
start_line_number + i,
|
||||||
|
calc_line_number_width(start_line_number),
|
||||||
|
),
|
||||||
|
None => line.to_string(),
|
||||||
|
},
|
||||||
|
frame_width_with_content - 1
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<String>();
|
||||||
|
let text_line = |text: &str| format!("│ {:1$}│\n", text, frame_width_with_content);
|
||||||
|
let breadcrumbs = optional(
|
||||||
|
format!("{}{line}", text_line(¶ms.file_path)),
|
||||||
|
params.has_breadcrumbs,
|
||||||
|
);
|
||||||
|
let ascii_snapshot = format!("{top_frame}{breadcrumbs}{code}{bottom_frame}");
|
||||||
|
|
||||||
|
Clipboard::new().unwrap().set_text(ascii_snapshot).unwrap();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ mod color;
|
||||||
mod components;
|
mod components;
|
||||||
mod config;
|
mod config;
|
||||||
mod copy;
|
mod copy;
|
||||||
|
mod copy_ascii;
|
||||||
mod edges;
|
mod edges;
|
||||||
mod highlight;
|
mod highlight;
|
||||||
mod path;
|
mod path;
|
||||||
|
@ -11,6 +12,7 @@ mod snapshot;
|
||||||
mod text;
|
mod text;
|
||||||
|
|
||||||
use copy::copy_into_clipboard;
|
use copy::copy_into_clipboard;
|
||||||
|
use copy_ascii::copy_ascii;
|
||||||
use nvim_oxi::{Dictionary, Function, Result};
|
use nvim_oxi::{Dictionary, Function, Result};
|
||||||
use save::save_snapshot;
|
use save::save_snapshot;
|
||||||
|
|
||||||
|
@ -22,5 +24,6 @@ fn generator() -> Result<Dictionary> {
|
||||||
Function::from_fn(copy_into_clipboard),
|
Function::from_fn(copy_into_clipboard),
|
||||||
),
|
),
|
||||||
("save_snapshot", Function::from_fn(save_snapshot)),
|
("save_snapshot", Function::from_fn(save_snapshot)),
|
||||||
|
("copy_ascii", Function::from_fn(copy_ascii)),
|
||||||
]))
|
]))
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,13 @@ function main.copy_into_clipboard_with_config(config)
|
||||||
vim.notify("Save snapshot into clipboard successfully")
|
vim.notify("Save snapshot into clipboard successfully")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Take ASCII code snapshot into clipboard
|
||||||
|
function main.copy_ascii_snapshot(extension)
|
||||||
|
require("generator").copy_ascii(config_module.get_config(extension))
|
||||||
|
vim.cmd("delmarks <>")
|
||||||
|
vim.notify("Save snapshot into clipboard successfully")
|
||||||
|
end
|
||||||
|
|
||||||
function main.save_snapshot_with_config(config)
|
function main.save_snapshot_with_config(config)
|
||||||
if string_utils.is_str_empty(static.config.save_path) then
|
if string_utils.is_str_empty(static.config.save_path) then
|
||||||
error(
|
error(
|
||||||
|
|
|
@ -23,6 +23,12 @@ vim.api.nvim_create_user_command("CodeSnap", take_snapshot(codesnap.copy_into_cl
|
||||||
|
|
||||||
vim.api.nvim_create_user_command("CodeSnapSave", take_snapshot(codesnap.save_snapshot), { nargs = "*", range = "%" })
|
vim.api.nvim_create_user_command("CodeSnapSave", take_snapshot(codesnap.save_snapshot), { nargs = "*", range = "%" })
|
||||||
|
|
||||||
|
vim.api.nvim_create_user_command(
|
||||||
|
"CodeSnapASCII",
|
||||||
|
take_snapshot(codesnap.copy_ascii_snapshot),
|
||||||
|
{ nargs = "*", range = "%" }
|
||||||
|
)
|
||||||
|
|
||||||
vim.api.nvim_create_user_command(
|
vim.api.nvim_create_user_command(
|
||||||
"CodeSnapHighlight",
|
"CodeSnapHighlight",
|
||||||
take_snapshot(codesnap.highlight_mode_copy_into_clipboard),
|
take_snapshot(codesnap.highlight_mode_copy_into_clipboard),
|
||||||
|
|
Loading…
Reference in New Issue