[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 logger
This commit is contained in:
The Mist 2024-07-05 05:00:50 -04:00 committed by GitHub
parent 8f03a0795b
commit b3e3c23146
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 101 additions and 7 deletions

View file

@ -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)
} }

View file

@ -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.,

View file

@ -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))
} }

View file

@ -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(&params.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(&params.file_path)),
params.has_breadcrumbs,
);
let ascii_snapshot = format!("{top_frame}{breadcrumbs}{code}{bottom_frame}");
Clipboard::new().unwrap().set_text(ascii_snapshot).unwrap();
Ok(())
}

View file

@ -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)),
])) ]))
} }

View file

@ -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(

View file

@ -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),