diff --git a/.github/workflows/contributor_list.yml b/.github/workflows/contributor_list.yml
new file mode 100644
index 0000000..346ffe1
--- /dev/null
+++ b/.github/workflows/contributor_list.yml
@@ -0,0 +1,19 @@
+name: Auto Generate Contributor List
+
+on:
+ push:
+ branches:
+ main
+
+permissions:
+ contents: write
+
+jobs:
+ generate-contributor-list:
+ name: Auto generate contributor list
+ runs-on: ubuntu-latest
+ steps:
+ - uses: wow-actions/contributors-list@v1
+ with:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ svgPath: CONTRIBUTORS.svg
diff --git a/.github/workflows/generate_toc.yml b/.github/workflows/generate_toc.yml
new file mode 100644
index 0000000..4a26134
--- /dev/null
+++ b/.github/workflows/generate_toc.yml
@@ -0,0 +1,21 @@
+name: Generate TOC
+
+on:
+ push:
+ paths:
+ README.md
+ branches:
+ main
+
+permissions:
+ contents: write
+
+jobs:
+ generate-toc:
+ name: TOC Generator
+ runs-on: ubuntu-latest
+ steps:
+ - uses: technote-space/toc-generator@v4
+ with:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ TOC_TITLE: ''
diff --git a/CONTRIBUTORS.svg b/CONTRIBUTORS.svg
new file mode 100644
index 0000000..cad2e85
--- /dev/null
+++ b/CONTRIBUTORS.svg
@@ -0,0 +1,33 @@
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 571dfa8..d565a30 100644
--- a/README.md
+++ b/README.md
@@ -4,19 +4,66 @@
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
CodeSnap.nvim
📸 Snapshot plugin with rich features that can make pretty code snapshots for Neovim
+
+
+
+- [🚣Migration](#migration)
+- [✨Features](#features)
+- [Prerequirements](#prerequirements)
+- [Install](#install)
+ - [Compile from source](#compile-from-source)
+ - [Compile on ARM](#compile-on-arm)
+ - [Keymappings](#keymappings)
+- [Usage](#usage)
+ - [Copy into the clipboard](#copy-into-the-clipboard)
+ - [Copy into clipboard on Linux Wayland](#copy-into-clipboard-on-linux-wayland)
+ - [Save the snapshot](#save-the-snapshot)
+ - [Highlight code block](#highlight-code-block)
+ - [How to use](#how-to-use)
+ - [Specify language extension](#specify-language-extension)
+- [Breadcrumbs](#breadcrumbs)
+ - [Show workspace in breadcrumbs](#show-workspace-in-breadcrumbs)
+ - [Custom path separator](#custom-path-separator)
+- [Line number](#line-number)
+- [Custom background](#custom-background)
+ - [Solid color background](#solid-color-background)
+- [Watermark](#watermark)
+- [Commands](#commands)
+- [Configuration](#configuration)
+- [Contribution](#contribution)
+ - [Contributors](#contributors)
+- [License](#license)
+
+
## 🚣Migration
If you have installed v0.x before, this chapter will show you what break changes version v1.x introduced.
@@ -34,7 +81,7 @@ v1.x has a different architecture and better performance than v0.x, and v1.x can
- 🤖 Generate snapshots using only a single command
- 🍞 Breadcrumbs for display file path
- 🌊 More beautiful background theme
-- 🔢 [WIP] Column number
+- 🔢 Support for display line number make sharing code snapshot easier
## Prerequirements
- Neovim 0.9.0+
@@ -85,6 +132,24 @@ sudo dnf install libuv libuv-devel # On RHEL based systems
sudo apt-get install libtool libuv1-dev # On Debian based systems
```
+### Keymappings
+If you use `Lazy.nvim` as your package manager, here are some examples show you how to configure keymappings for CodeSnap:
+```lua
+{
+ "mistricky/codesnap.nvim",
+ build = "make build_generator",
+ keys = {
+ { "cc", "CodeSnap", mode = "x", desc = "Save selected code snapshot into clipboard" },
+ { "cs", "CodeSnapSave", mode = "x", desc = "Save selected code snapshot in ~/Pictures" },
+ },
+ opts = {
+ save_path = "~/Pictures",
+ has_breadcrumbs = true,
+ bg_theme = "bamboo",
+ },
+}
+```
+
## Usage
`CodeSnap.nvim` provides the following two ways to take snapshots of currently selected code
@@ -122,6 +187,25 @@ require("codesnap").setup({
https://github.com/mistricky/codesnap.nvim/assets/22574136/69b27e77-3dce-4bc3-8516-89ce636fe02d
+### Highlight code block
+
+CodeSnap allows you to take code snapshots with highlights code blocks, we provide two commands for this scenario:
+
+```shell
+CodeSnapHighlight # Take code snapshot with highlights code blocks and copy it into the clipboard
+CodeSnapSaveHighlight # Take code snapshot with highlights code blocks and save it somewhere
+```
+
+#### How to use
+For take a code snapshot with highlights code blocks and save it somewhere. First you need to select code which you want to snapshot, then enter the command `CodeSnapSaveHighlight` to open a window show you the selected code which from previous step, now you can select code which you want to highlight, finally press the Enter key, CodeSnap will generate a snapshot with highlight blocks and save it in save_path.
+
+Here is an example video:
+
+https://github.com/mistricky/codesnap.nvim/assets/22574136/bea0bf6c-8fc9-4d09-9cab-4e1e6f47899c
+
+
+
+
### Specify language extension
In some scenarios, CodeSnap.nvim cannot auto-detect what language syntax should used to highlight code, for example, shell script can have no extension, they specify interpreters using shebang.
@@ -144,6 +228,16 @@ require("codesnap").setup({
The breadcrumbs look like:
![image](https://github.com/mistricky/codesnap.nvim/assets/22574136/23274faa-36a9-4d41-88a5-e48c44b4d5bf)
+### Show workspace in breadcrumbs
+Breadcrumbs hide the workspace name by default, if you want to display workspace in breadcrumbs, you can just set `show_workspace` as true.
+```lua
+require("codesnap").setup({
+ -- ...
+ has_breadcrumbs = true
+ show_workspace = true
+})
+```
+
### Custom path separator
The CodeSnap.nvim uses `/` as the separator of the file path by default, of course, you can specify any symbol you prefer as the custom separator:
```lua
@@ -157,6 +251,17 @@ require("codesnap").setup({
![image](https://github.com/mistricky/codesnap.nvim/assets/22574136/84b80d0f-1467-4bdf-9cbd-aede868f93aa)
+## Line number
+We also support displaying line number, you can set `has_line_number` to true to display line number.
+```lua
+require("codesnap").setup({
+ // ...
+ has_line_number = true,
+})
+```
+
+![image](https://github.com/mistricky/codesnap.nvim/assets/22574136/3a5999b1-bb2a-4646-8d69-609be1d28140)
+
## Custom background
The `CodeSnap.nvim` comes with many beautiful backgrounds preset, you can set any background you like by setting `bg_theme` to its name, just like:
@@ -236,6 +341,16 @@ CodeSnap # Take a snapshot of the currently selected code and copy the snapshot
CodeSnapSave # Save the snapshot of the currently selected code and save it on the disk
```
+**Lua**
+```lua
+local codesnap = require("codesnap")
+
+-- Take a snapshot of the currently selected code and copy the snapshot into the clipboard
+codesnap.copy_into_clipboard()
+
+-- Save the snapshot of the currently selected code and save it on the disk
+codesnap.save_snapshot()
+```
## Configuration
Define your custom config using `setup` function
@@ -254,6 +369,8 @@ There is a default config:
bg_theme = "default",
breadcrumbs_separator = "/",
has_breadcrumbs = false,
+ has_line_number = false,
+ min_width = 0
}
```
@@ -262,5 +379,10 @@ CodeSnap.nvim is a project that will be maintained for the long term, and we alw
The commit message convention of this project is following [commitlint-wizardoc](https://github.com/wizardoc/commitlint-wizardoc).
+### Contributors
+Thanks to all contributors for their contributions and works they have done.
+
+
+
## License
MIT.
diff --git a/doc/plugin-name.txt b/doc/plugin-name.txt
index ed33c2f..0e473b7 100644
--- a/doc/plugin-name.txt
+++ b/doc/plugin-name.txt
@@ -1,4 +1,4 @@
**codesnap.nvim** 📸 Snapshot plugin that can make pretty code snapshots with real-time previews for Neovim
Author: Mist
-version: 1.1.12
+version: 1.3.1
diff --git a/generator/Cargo.lock b/generator/Cargo.lock
index 06a04d1..90603f3 100644
--- a/generator/Cargo.lock
+++ b/generator/Cargo.lock
@@ -8,6 +8,18 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+[[package]]
+name = "ahash"
+version = "0.8.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+ "version_check",
+ "zerocopy",
+]
+
[[package]]
name = "aho-corasick"
version = "1.1.2"
@@ -17,6 +29,12 @@ dependencies = [
"memchr",
]
+[[package]]
+name = "allocator-api2"
+version = "0.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
+
[[package]]
name = "arboard"
version = "3.3.2"
@@ -87,7 +105,7 @@ dependencies = [
"regex",
"rustc-hash",
"shlex",
- "syn",
+ "syn 2.0.52",
]
[[package]]
@@ -120,6 +138,39 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
+[[package]]
+name = "cached"
+version = "0.49.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e8e463fceca5674287f32d252fb1d94083758b8709c160efae66d263e5f4eba"
+dependencies = [
+ "ahash",
+ "cached_proc_macro",
+ "cached_proc_macro_types",
+ "hashbrown",
+ "instant",
+ "once_cell",
+ "thiserror",
+]
+
+[[package]]
+name = "cached_proc_macro"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad9f16c0d84de31a2ab7fdf5f7783c14631f7075cf464eb3bb43119f61c9cb2a"
+dependencies = [
+ "darling",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "cached_proc_macro_types"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ade8366b8bd5ba243f0a58f036cc0ca8a2f069cff1a2351ef1cac6b083e16fc0"
+
[[package]]
name = "cc"
version = "1.0.90"
@@ -245,6 +296,41 @@ dependencies = [
"cfg-if",
]
+[[package]]
+name = "darling"
+version = "0.14.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850"
+dependencies = [
+ "darling_core",
+ "darling_macro",
+]
+
+[[package]]
+name = "darling_core"
+version = "0.14.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0"
+dependencies = [
+ "fnv",
+ "ident_case",
+ "proc-macro2",
+ "quote",
+ "strsim",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "darling_macro"
+version = "0.14.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e"
+dependencies = [
+ "darling_core",
+ "quote",
+ "syn 1.0.109",
+]
+
[[package]]
name = "deranged"
version = "0.3.11"
@@ -262,7 +348,7 @@ checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.52",
]
[[package]]
@@ -386,7 +472,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.52",
]
[[package]]
@@ -400,6 +486,7 @@ name = "generator"
version = "0.1.0"
dependencies = [
"arboard",
+ "cached",
"cosmic-text",
"nvim-oxi",
"regex",
@@ -433,6 +520,10 @@ name = "hashbrown"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
+dependencies = [
+ "ahash",
+ "allocator-api2",
+]
[[package]]
name = "home"
@@ -443,6 +534,12 @@ dependencies = [
"windows-sys 0.52.0",
]
+[[package]]
+name = "ident_case"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
+
[[package]]
name = "image"
version = "0.24.9"
@@ -467,6 +564,15 @@ dependencies = [
"hashbrown",
]
+[[package]]
+name = "instant"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+dependencies = [
+ "cfg-if",
+]
+
[[package]]
name = "itoa"
version = "1.0.10"
@@ -762,7 +868,7 @@ checksum = "7fa77de5791207f41bab307dadb91e66a2bbbd19433e4243ef98c9d45e03a007"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.52",
]
[[package]]
@@ -1033,7 +1139,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.52",
]
[[package]]
@@ -1055,7 +1161,7 @@ checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.52",
]
[[package]]
@@ -1091,6 +1197,12 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
+[[package]]
+name = "strsim"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+
[[package]]
name = "swash"
version = "0.1.12"
@@ -1102,6 +1214,17 @@ dependencies = [
"zeno",
]
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
[[package]]
name = "syn"
version = "2.0.52"
@@ -1183,7 +1306,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.52",
]
[[package]]
@@ -1669,3 +1792,23 @@ name = "zeno"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd15f8e0dbb966fd9245e7498c7e9e5055d9e5c8b676b95bd67091cd11a1e697"
+
+[[package]]
+name = "zerocopy"
+version = "0.7.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.7.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.52",
+]
diff --git a/generator/Cargo.toml b/generator/Cargo.toml
index 1d298fa..8ddc8d8 100644
--- a/generator/Cargo.toml
+++ b/generator/Cargo.toml
@@ -13,6 +13,7 @@ arboard = {features = ["wayland-data-control"], version = "3.3.2"}
thiserror = "1.0.58"
regex = "1.10.3"
two-face = "0.3.0"
+cached = "0.49.3"
wsl = "0.1.0"
sys-info = "0.9.1"
diff --git a/generator/src/code.rs b/generator/src/code.rs
index c1e6cde..2b0849a 100644
--- a/generator/src/code.rs
+++ b/generator/src/code.rs
@@ -1,6 +1,8 @@
+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 {
@@ -10,6 +12,9 @@ fn min_width(width: f32) -> f32 {
}
}
+// 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(text: &str, char_wdith: f32, line_height: f32) -> (f32, f32) {
let trimmed_text = prepare_code(text);
let lines = trimmed_text.lines();
@@ -34,29 +39,33 @@ fn replace_tab_to_space(text: &str) -> String {
str::replace(text, "\t", &spaces)
}
-// If the first line have indention, remove the same indention from subsequent lines
+// Find min indention of code lines, and remove the same indention from subsequent lines
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);
+ let regex = Regex::new(r"(?:^|\n)(\s*)").unwrap();
+ let captures_iter = regex.captures_iter(text);
+ let space_lengths = captures_iter
+ .map(|capture| capture.get(1).unwrap().as_str().len())
+ .collect::>();
- 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(),
+ if space_lengths.len() < lines.len() {
+ return text.to_string();
}
+
+ let need_to_remove_spaces = " ".repeat(space_lengths.into_iter().min().unwrap());
+
+ lines
+ .into_iter()
+ .map(|line| {
+ Regex::new(format!("^{}", need_to_remove_spaces).as_ref())
+ .unwrap()
+ .replace(line, "")
+ .to_string()
+ })
+ .collect::>()
+ .join("\n")
}
pub fn prepare_code(code: &str) -> String {
- replace_tab_to_space(&trim_space(&code))
+ trim_space(&replace_tab_to_space(&code))
}
diff --git a/generator/src/components.rs b/generator/src/components.rs
index c14e6db..6a31557 100644
--- a/generator/src/components.rs
+++ b/generator/src/components.rs
@@ -1,7 +1,10 @@
pub mod background;
pub mod breadcrumbs;
+pub mod code_block;
pub mod container;
pub mod editor;
+pub mod highlight_code_block;
pub mod interface;
+pub mod line_number;
pub mod rect;
pub mod watermark;
diff --git a/generator/src/components/background.rs b/generator/src/components/background.rs
index 8b4ca83..6fa69e2 100644
--- a/generator/src/components/background.rs
+++ b/generator/src/components/background.rs
@@ -35,6 +35,7 @@ impl Component for Background {
context: &ComponentContext,
_render_params: &RenderParams,
_style: &ComponentStyle,
+ _parent_style: &ComponentStyle,
) -> render_error::Result<()> {
let mut paint = Paint::default();
let w = pixmap.width() as f32;
diff --git a/generator/src/components/breadcrumbs.rs b/generator/src/components/breadcrumbs.rs
index e096dda..a41d44b 100644
--- a/generator/src/components/breadcrumbs.rs
+++ b/generator/src/components/breadcrumbs.rs
@@ -5,7 +5,7 @@ use crate::{code::calc_wh, edges::margin::Margin, text::FontRenderer};
use super::interface::{
component::Component,
- style::{RawComponentStyle, Size},
+ style::{ComponentStyle, RawComponentStyle, Size},
};
pub struct Breadcrumbs {
@@ -41,6 +41,7 @@ impl Component for Breadcrumbs {
context: &super::interface::component::ComponentContext,
render_params: &super::interface::component::RenderParams,
style: &super::interface::style::ComponentStyle,
+ _parent_style: &ComponentStyle,
) -> super::interface::render_error::Result<()> {
if self.has_breadcrumbs {
let attrs = Attrs::new()
diff --git a/generator/src/components/code_block.rs b/generator/src/components/code_block.rs
new file mode 100644
index 0000000..d103ba8
--- /dev/null
+++ b/generator/src/components/code_block.rs
@@ -0,0 +1,29 @@
+use crate::edges::margin::Margin;
+
+use super::interface::{
+ component::Component,
+ style::{RawComponentStyle, Style},
+};
+
+pub struct CodeBlock {
+ children: Vec>,
+}
+
+impl Component for CodeBlock {
+ fn children(&self) -> &Vec> {
+ &self.children
+ }
+
+ fn style(&self) -> RawComponentStyle {
+ Style::default().margin(Margin {
+ top: 10.,
+ ..Margin::default()
+ })
+ }
+}
+
+impl CodeBlock {
+ pub fn from_children(children: Vec>) -> CodeBlock {
+ CodeBlock { children }
+ }
+}
diff --git a/generator/src/components/editor/code.rs b/generator/src/components/editor/code.rs
index 40f8c06..7219d44 100644
--- a/generator/src/components/editor/code.rs
+++ b/generator/src/components/editor/code.rs
@@ -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(
@@ -39,6 +33,7 @@ impl Component for Code {
context: &ComponentContext,
render_params: &RenderParams,
style: &ComponentStyle,
+ _parent_style: &ComponentStyle,
) -> render_error::Result<()> {
let params = &context.take_snapshot_params;
let highlight = Highlight::new(
diff --git a/generator/src/components/editor/mac_title_bar.rs b/generator/src/components/editor/mac_title_bar.rs
index acf67c2..e112ad3 100644
--- a/generator/src/components/editor/mac_title_bar.rs
+++ b/generator/src/components/editor/mac_title_bar.rs
@@ -33,6 +33,7 @@ impl Component for MacTitleBar {
context: &ComponentContext,
render_params: &RenderParams,
_style: &ComponentStyle,
+ _parent_style: &ComponentStyle,
) -> render_error::Result<()> {
self.draw_control_buttons(
// Control bar construct by draw circles, after drawn, the path will be at the center,
diff --git a/generator/src/components/highlight_code_block.rs b/generator/src/components/highlight_code_block.rs
new file mode 100644
index 0000000..cbefc09
--- /dev/null
+++ b/generator/src/components/highlight_code_block.rs
@@ -0,0 +1,76 @@
+use super::{
+ interface::{component::Component, style::ComponentStyle},
+ rect::EDITOR_PADDING,
+};
+use tiny_skia::{Color, Paint, Rect, Transform};
+
+#[derive(Default)]
+pub struct HighlightCodeBlock {
+ children: Vec>,
+ line_height: f32,
+ start_line_number: usize,
+ end_line_number: usize,
+ render_condition: bool,
+}
+
+impl Component for HighlightCodeBlock {
+ fn children(&self) -> &Vec> {
+ &self.children
+ }
+
+ fn render_condition(&self) -> bool {
+ self.render_condition
+ }
+
+ 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,
+ parent_style: &ComponentStyle,
+ ) -> super::interface::render_error::Result<()> {
+ let mut paint = Paint::default();
+ let start_y_offset = (self.start_line_number - 1) as f32 * self.line_height;
+
+ paint.anti_alias = false;
+ paint.set_color(Color::from_rgba8(255, 255, 255, 10));
+ pixmap.fill_rect(
+ Rect::from_xywh(
+ render_params.x - EDITOR_PADDING,
+ render_params.y + start_y_offset,
+ parent_style.width + EDITOR_PADDING * 2.,
+ (self.end_line_number - self.start_line_number + 1) as f32 * self.line_height,
+ )
+ .unwrap(),
+ &paint,
+ Transform::from_scale(context.scale_factor, context.scale_factor),
+ None,
+ );
+
+ Ok(())
+ }
+}
+
+impl HighlightCodeBlock {
+ pub fn from_line_number(
+ start_line_number: Option,
+ end_line_number: Option,
+ line_height: f32,
+ ) -> HighlightCodeBlock {
+ if end_line_number < start_line_number {
+ panic!("end_line_number should be greater than start_line_number")
+ }
+
+ match start_line_number {
+ Some(start_line_number) => HighlightCodeBlock {
+ render_condition: true,
+ children: vec![],
+ line_height,
+ start_line_number,
+ end_line_number: end_line_number.unwrap(),
+ },
+ None => HighlightCodeBlock::default(),
+ }
+ }
+}
diff --git a/generator/src/components/interface/component.rs b/generator/src/components/interface/component.rs
index 2bef71a..0275748 100644
--- a/generator/src/components/interface/component.rs
+++ b/generator/src/components/interface/component.rs
@@ -1,13 +1,10 @@
-use std::sync::Arc;
-
-use tiny_skia::Pixmap;
-
-use crate::{config::TakeSnapshotParams, edges::edge::Edge};
-
use super::{
render_error,
style::{ComponentAlign, ComponentStyle, RawComponentStyle, Size, Style},
};
+use crate::{config::TakeSnapshotParams, edges::edge::Edge};
+use std::sync::Arc;
+use tiny_skia::Pixmap;
pub struct ComponentContext {
pub scale_factor: f32,
@@ -73,6 +70,7 @@ pub trait Component {
_context: &ComponentContext,
_render_params: &RenderParams,
_style: &ComponentStyle,
+ _parent_style: &ComponentStyle,
) -> render_error::Result<()> {
Ok(())
}
@@ -91,11 +89,17 @@ pub trait Component {
fn parsed_style(&self) -> Style {
let style = self.style();
let (width, height) = self.get_dynamic_wh();
+ let width = self.parse_size(style.width, width)
+ + style.padding.horizontal()
+ + style.margin.horizontal();
Style {
- width: self.parse_size(style.width, width)
- + style.padding.horizontal()
- + style.margin.horizontal(),
+ min_width: style.min_width,
+ width: if width > style.min_width {
+ width
+ } else {
+ style.min_width
+ },
height: self.parse_size(style.height, height)
+ style.padding.vertical()
+ style.margin.vertical(),
@@ -116,13 +120,13 @@ pub trait Component {
let style = self.parsed_style();
let render_params = self.initialize(
&component_render_params.parse_into_render_params_with_style(
- parent_style,
+ parent_style.clone(),
sibling_style,
style.clone(),
),
);
- self.draw_self(pixmap, context, &render_params, &style)?;
+ self.draw_self(pixmap, context, &render_params, &style, &parent_style)?;
let children = self.children();
let mut sibling_render_params = RenderParams {
@@ -152,6 +156,8 @@ pub trait Component {
Ok(render_params.clone())
}
+ // Dynamic calculate width and height of children, if the children is empty, get_dynamic_wh
+ // will return (0., 0.)
fn get_dynamic_wh(&self) -> (f32, f32) {
let children = self.children();
let calc_children_wh = |cb: fn((f32, f32), &Box) -> (f32, f32)| {
@@ -160,11 +166,13 @@ pub trait Component {
let style = self.style();
match style.align {
+ // If align is row, width is sum of children width, height is max of children height
ComponentAlign::Row => calc_children_wh(|(w, h), child| {
let style = child.parsed_style();
(w + style.width, h.max(style.height))
}),
+ // If align is column, width is max of children width, height is sum of children height
ComponentAlign::Column => calc_children_wh(|(w, h), child| {
let style = child.parsed_style();
diff --git a/generator/src/components/interface/style.rs b/generator/src/components/interface/style.rs
index 94a6f09..bdc5fec 100644
--- a/generator/src/components/interface/style.rs
+++ b/generator/src/components/interface/style.rs
@@ -15,6 +15,7 @@ pub enum Size {
pub struct Style {
pub width: T,
pub height: T,
+ pub min_width: f32,
pub align: ComponentAlign,
pub padding: Padding,
pub margin: Margin,
@@ -26,6 +27,7 @@ pub type ComponentStyle = Style;
impl Default for RawComponentStyle {
fn default() -> Self {
Style {
+ min_width: 0.,
width: Size::Dynamic,
height: Size::Dynamic,
align: ComponentAlign::Row,
@@ -38,6 +40,7 @@ impl Default for RawComponentStyle {
impl Default for ComponentStyle {
fn default() -> Self {
Style {
+ min_width: 0.,
width: 0.,
height: 0.,
align: ComponentAlign::Row,
@@ -54,6 +57,12 @@ impl RawComponentStyle {
self
}
+ // Only works if the width is calculate dynamically
+ pub fn min_width(mut self, min_width: f32) -> Self {
+ self.min_width = min_width;
+ self
+ }
+
pub fn align(mut self, align: ComponentAlign) -> Self {
self.align = align;
self
diff --git a/generator/src/components/line_number.rs b/generator/src/components/line_number.rs
new file mode 100644
index 0000000..b2a9ca1
--- /dev/null
+++ b/generator/src/components/line_number.rs
@@ -0,0 +1,100 @@
+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>,
+ line_height: f32,
+ render_condition: bool,
+ line_number_content: Vec,
+ number_of_digit: usize,
+}
+
+impl Component for LineNumber {
+ fn render_condition(&self) -> bool {
+ return self.render_condition;
+ }
+
+ fn children(&self) -> &Vec> {
+ &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,
+ _parent_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, line_height: f32) -> LineNumber {
+ match start_line_number {
+ None => LineNumber::default(),
+ Some(start_line_number) => {
+ let lines = content.split("\n").collect::>();
+ 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::>(),
+ number_of_digit,
+ children: vec![],
+ render_condition: true,
+ line_height,
+ }
+ }
+ }
+ }
+}
diff --git a/generator/src/components/rect.rs b/generator/src/components/rect.rs
index 2fdc489..dd97b2d 100644
--- a/generator/src/components/rect.rs
+++ b/generator/src/components/rect.rs
@@ -1,14 +1,16 @@
-use crate::edges::padding::Padding;
-
use super::interface::{
component::{Component, ComponentContext, RenderParams},
render_error,
style::{ComponentAlign, ComponentStyle, RawComponentStyle, Style},
};
+use crate::edges::padding::Padding;
use tiny_skia::{FillRule, Paint, PathBuilder, Pixmap, Transform};
+pub const EDITOR_PADDING: f32 = 20.;
+
pub struct Rect {
radius: f32,
+ min_width: f32,
children: Vec>,
}
@@ -19,8 +21,9 @@ impl Component for Rect {
fn style(&self) -> RawComponentStyle {
Style::default()
+ .min_width(self.min_width)
.align(ComponentAlign::Column)
- .padding(Padding::from_value(20.))
+ .padding(Padding::from_value(EDITOR_PADDING))
}
fn draw_self(
@@ -29,6 +32,7 @@ impl Component for Rect {
context: &ComponentContext,
render_params: &RenderParams,
style: &ComponentStyle,
+ _parent_style: &ComponentStyle,
) -> render_error::Result<()> {
let mut path_builder = PathBuilder::new();
let x = render_params.x;
@@ -92,7 +96,11 @@ impl Component for Rect {
}
impl Rect {
- pub fn new(radius: f32, children: Vec>) -> Rect {
- Rect { radius, children }
+ pub fn new(radius: f32, min_width: Option, children: Vec>) -> Rect {
+ Rect {
+ radius,
+ children,
+ min_width: min_width.unwrap_or(0.),
+ }
}
}
diff --git a/generator/src/components/watermark.rs b/generator/src/components/watermark.rs
index 8007413..7cb6f8a 100644
--- a/generator/src/components/watermark.rs
+++ b/generator/src/components/watermark.rs
@@ -21,6 +21,7 @@ impl Component for Watermark {
context: &ComponentContext,
render_params: &RenderParams,
_style: &ComponentStyle,
+ _parent_style: &ComponentStyle,
) -> render_error::Result<()> {
let params = &context.take_snapshot_params;
diff --git a/generator/src/config.rs b/generator/src/config.rs
index c1e955a..8b6158e 100644
--- a/generator/src/config.rs
+++ b/generator/src/config.rs
@@ -26,6 +26,10 @@ pub struct TakeSnapshotParams {
pub file_path: String,
pub breadcrumbs_separator: String,
pub has_breadcrumbs: bool,
+ pub start_line_number: Option,
+ pub highlight_start_line_number: Option,
+ pub highlight_end_line_number: Option,
+ pub min_width: Option,
}
impl FromObject for TakeSnapshotParams {
diff --git a/generator/src/highlight.rs b/generator/src/highlight.rs
index 3d2096f..3df50e1 100644
--- a/generator/src/highlight.rs
+++ b/generator/src/highlight.rs
@@ -53,6 +53,9 @@ impl Highlight {
))?,
};
+ // The Syntect clearly distinguish between PHP and PHP Source
+ // Should use PHP as highlight language if the source content contains " attrs.weight(Weight::BOLD),
+ FontStyle::ITALIC => attrs.style(Style::Italic),
+ FontStyle::UNDERLINE => attrs.style(Style::Normal),
+ _ => attrs,
+ };
+
+ (str, attrs.color(cosmic_text::Color::rgb(r, g, b)))
+ })
+ .collect::()
+ })
.fold(vec![], |acc, cur| [acc, cur].concat())
.into_iter()
- .map(move |(style, str)| {
- let syntect::highlighting::Color { r, g, b, a: _ } = style.foreground;
- let attrs = match style.font_style {
- FontStyle::BOLD => attrs.weight(Weight::BOLD),
- FontStyle::ITALIC => attrs.style(Style::Italic),
- FontStyle::UNDERLINE => attrs.style(Style::Normal),
- _ => attrs,
- };
-
- (str, attrs.color(cosmic_text::Color::rgb(r, g, b)))
- })
.collect::())
}
}
diff --git a/generator/src/snapshot.rs b/generator/src/snapshot.rs
index daeb410..cbf14bc 100644
--- a/generator/src/snapshot.rs
+++ b/generator/src/snapshot.rs
@@ -4,17 +4,21 @@ 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::highlight_code_block::HighlightCodeBlock;
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;
// Scale the screenshot to 3 times its size
const SCALE_FACTOR: f32 = 3.;
+const LINE_HEIGHT: f32 = 20.;
// The params is come from neovim instance
pub fn take_snapshot(params: TakeSnapshotParams) -> render_error::Result {
@@ -25,6 +29,7 @@ pub fn take_snapshot(params: TakeSnapshotParams) -> render_error::Result
let pixmap = Container::from_children(vec![Box::new(Background::from_children(vec![
Box::new(Rect::new(
16.,
+ params.min_width,
vec![
Box::new(MacTitleBar::from_radius(8., params.mac_window_bar)),
Box::new(Breadcrumbs::from_path(
@@ -33,7 +38,19 @@ pub fn take_snapshot(params: TakeSnapshotParams) -> render_error::Result
params.breadcrumbs_separator,
params.has_breadcrumbs,
)),
- Box::new(Code::new(params.code, 20., 15.)),
+ Box::new(CodeBlock::from_children(vec![
+ Box::new(HighlightCodeBlock::from_line_number(
+ params.highlight_start_line_number,
+ params.highlight_end_line_number,
+ LINE_HEIGHT,
+ )),
+ Box::new(LineNumber::new(
+ ¶ms.code,
+ params.start_line_number,
+ LINE_HEIGHT,
+ )),
+ Box::new(Code::new(params.code, LINE_HEIGHT, 15.)),
+ ])),
],
)),
Box::new(Watermark::new(params.watermark)),
diff --git a/lua/codesnap/client.lua b/lua/codesnap/client.lua
deleted file mode 100644
index c0ec413..0000000
--- a/lua/codesnap/client.lua
+++ /dev/null
@@ -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
diff --git a/lua/codesnap/config.lua b/lua/codesnap/config.lua
index 0d7cded..a91121b 100644
--- a/lua/codesnap/config.lua
+++ b/lua/codesnap/config.lua
@@ -25,8 +25,15 @@ local function parse_save_path(save_path)
return parsed_save_path .. auto_generate_snap_filename()
end
+local function get_file_path(show_workspace)
+ local relative_path = path_utils.get_relative_path()
+
+ return show_workspace and path_utils.get_workspace() .. "/" .. relative_path or relative_path
+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)
@@ -40,7 +47,8 @@ function config_module.get_config(extension)
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 "",
+ file_path = static.config.has_breadcrumbs and get_file_path(static.config.show_workspace) 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)
diff --git a/lua/codesnap/highlight.lua b/lua/codesnap/highlight.lua
new file mode 100644
index 0000000..7f7c952
--- /dev/null
+++ b/lua/codesnap/highlight.lua
@@ -0,0 +1,55 @@
+local string_utils = require("codesnap.utils.string")
+local table_utils = require("codesnap.utils.table")
+local highlight_module = {}
+
+function highlight_module.call_cb_with_parsed_config(cb_name, highlight_start_line_number, highlight_end_line_number)
+ vim.api.nvim_buf_delete(0, {})
+ vim.schedule(function()
+ local main = require("codesnap")
+ local config = table_utils.merge(main.highlight_mode_config, {
+ highlight_start_line_number = highlight_start_line_number,
+ highlight_end_line_number = highlight_end_line_number,
+ })
+
+ main[cb_name](config)
+ end)
+end
+
+function highlight_module.create_highlight_selector_window(cb_name, code)
+ local width = 100
+ local height = #code + 2
+ local row = vim.fn.winheight(0) / 2 - height / 2
+ local col = vim.fn.winwidth(0) / 2 - width / 2
+ local bufnr = vim.api.nvim_create_buf(false, true)
+
+ vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, code)
+
+ local window_id = vim.api.nvim_open_win(bufnr, false, {
+ relative = "editor",
+ width = width,
+ height = height,
+ col = col,
+ row = row,
+ style = "minimal",
+ border = "rounded",
+ title = "Select highlight lines",
+ title_pos = "center",
+ })
+
+ vim.api.nvim_buf_set_option(bufnr, "modifiable", false)
+ vim.api.nvim_buf_set_option(bufnr, "filetype", vim.bo.filetype)
+ vim.api.nvim_buf_set_keymap(bufnr, "n", "q", ":q", {})
+ vim.api.nvim_buf_set_keymap(bufnr, "", "", ":q", {})
+ vim.api.nvim_buf_set_keymap(
+ bufnr,
+ "v",
+ "",
+ ":lua require('codesnap.highlight').call_cb_with_parsed_config('"
+ .. cb_name
+ .. "', require('codesnap.utils.visual').get_start_line_number(), require('codesnap.utils.visual').get_end_line_number())",
+ { silent = true }
+ )
+ vim.api.nvim_set_current_win(window_id)
+end
+
+return highlight_module
diff --git a/lua/codesnap/init.lua b/lua/codesnap/init.lua
index 8340208..2b3f2ea 100644
--- a/lua/codesnap/init.lua
+++ b/lua/codesnap/init.lua
@@ -1,24 +1,27 @@
local static = require("codesnap.static")
+local visual_utils = require("codesnap.utils.visual")
local table_utils = require("codesnap.utils.table")
local string_utils = require("codesnap.utils.string")
local config_module = require("codesnap.config")
+local highlight_module = require("codesnap.highlight")
local main = {
cwd = static.cwd,
preview_switch = static.preview_switch,
+ highlight_mode_config = nil,
}
function main.setup(config)
static.config = table_utils.merge(static.config, config == nil and {} or config)
end
-function main.copy_into_clipboard(extension)
- require("generator").copy_into_clipboard(config_module.get_config(extension))
+function main.copy_into_clipboard_with_config(config)
+ require("generator").copy_into_clipboard(config)
vim.cmd("delmarks <>")
vim.notify("Save snapshot into clipboard successfully")
end
-function main.save_snapshot(extension)
+function main.save_snapshot_with_config(config)
if string_utils.is_str_empty(static.config.save_path) then
error(
"If you want to save snapshot in somewhere, you should config the save_path before, refer: https://github.com/mistricky/codesnap.nvim?tab=readme-ov-file#save-the-snapshot",
@@ -32,11 +35,35 @@ function main.save_snapshot(extension)
error("The extension of save_path should be .png", 0)
end
- local config = config_module.get_config(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
+-- Take a snapshot and copy it into clipboard
+function main.copy_into_clipboard(extension)
+ main.copy_into_clipboard_with_config(config_module.get_config(extension))
+end
+
+-- Take a snapshot and save it into the specified path
+function main.save_snapshot(extension)
+ main.save_snapshot_with_config(config_module.get_config(extension))
+end
+
+function main.highlight_mode_copy_into_clipboard(extension)
+ main.highlight_mode_config = config_module.get_config(extension)
+
+ highlight_module.create_highlight_selector_window(
+ "copy_into_clipboard_with_config",
+ visual_utils.get_selected_lines()
+ )
+end
+
+function main.highlight_mode_save_snapshot(extension)
+ main.highlight_mode_config = config_module.get_config(extension)
+
+ highlight_module.create_highlight_selector_window("save_snapshot_with_config", visual_utils.get_selected_lines())
+end
+
return main
diff --git a/lua/codesnap/static.lua b/lua/codesnap/static.lua
index 518158e..4ae9869 100644
--- a/lua/codesnap/static.lua
+++ b/lua/codesnap/static.lua
@@ -10,6 +10,9 @@ return {
bg_theme = "default",
breadcrumbs_separator = "/",
has_breadcrumbs = false,
+ has_line_number = false,
+ show_workspace = false,
+ min_width = 0,
},
cwd = path_utils.back(path_utils.back(debug.getinfo(1, "S").source:sub(2):match("(.*[/\\])"))),
preview_switch = true,
diff --git a/lua/codesnap/utils/logger.lua b/lua/codesnap/utils/logger.lua
deleted file mode 100644
index 168de3a..0000000
--- a/lua/codesnap/utils/logger.lua
+++ /dev/null
@@ -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
diff --git a/lua/codesnap/utils/path.lua b/lua/codesnap/utils/path.lua
index ebf4a54..6318c3e 100644
--- a/lua/codesnap/utils/path.lua
+++ b/lua/codesnap/utils/path.lua
@@ -1,17 +1,29 @@
local string_utils = require("codesnap.utils.string")
local path_utils = {}
+function path_utils.get_escaped_cwd()
+ local cwd = vim.fn.getcwd()
+
+ return string_utils.escape(cwd)
+end
+
function path_utils.back(path)
local parsed_path, _ = path:gsub("/[^\\/]+/?$", "")
return parsed_path
end
+function path_utils.get_workspace()
+ local cwd = vim.fn.getcwd()
+ local _, _, workspace = string.find(cwd, "/([^/]+)$")
+
+ return workspace == nil and "" or workspace
+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)
+ return full_file_path:gsub(path_utils.get_escaped_cwd(), ""):sub(2)
end
return path_utils
diff --git a/lua/codesnap/utils/string.lua b/lua/codesnap/utils/string.lua
index 00c6648..3398eb2 100644
--- a/lua/codesnap/utils/string.lua
+++ b/lua/codesnap/utils/string.lua
@@ -24,4 +24,14 @@ function string_util.convert_empty_to_nil(target)
end
end
+function string_util.split(str, delimiter)
+ local result = {}
+
+ for token in string.gmatch(str, "[^" .. delimiter .. "]+") do
+ table.insert(result, token)
+ end
+
+ return result
+end
+
return string_util
diff --git a/lua/codesnap/utils/table.lua b/lua/codesnap/utils/table.lua
index 732912a..bfb993a 100644
--- a/lua/codesnap/utils/table.lua
+++ b/lua/codesnap/utils/table.lua
@@ -33,7 +33,7 @@ end
function table_utils.serialize_array(t)
local result = list_utils.map(t, function(ele)
- table_utils.serialize_json(ele)
+ table_utils.to_string(ele)
end)
return "[" .. result.concat(t, ",") .. "]"
@@ -43,17 +43,17 @@ function table_utils.serialize_table(t)
local result = {}
for key, value in pairs(t) do
- table.insert(result, string.format('"%s":%s', key, table_utils.serialize_json(value)))
+ table.insert(result, string.format("%s = %s", key, table_utils.to_string(value)))
end
return "{" .. table.concat(result, ",") .. "}"
end
function table_utils.serialize_string(value)
- return '"' .. value .. '"'
+ return "[[" .. value .. "]]"
end
-function table_utils.serialize_json(t)
+function table_utils.to_string(t)
local complex_type_parser = {
array = table_utils.serialize_array,
table = table_utils.serialize_table,
@@ -67,4 +67,14 @@ function table_utils.serialize_json(t)
return parse(t)
end
+-- function table_utils.to_string(t)
+-- local result = ""
+--
+-- for key, value in pairs(t) do
+-- result = result .. key .. ":" .. tostring(value) .. ","
+-- end
+--
+-- return "{" .. result .. "}"
+-- end
+
return table_utils
diff --git a/lua/codesnap/utils/visual.lua b/lua/codesnap/utils/visual.lua
index f834ec4..49fff13 100644
--- a/lua/codesnap/utils/visual.lua
+++ b/lua/codesnap/utils/visual.lua
@@ -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,10 +14,20 @@ local function get_whole_lines(from, to)
return table.concat(lines, "\n")
end
-function visual_utils.get_selected_text()
- local selected_text = vim.fn.getline("'<", "'>")
+function visual_utils.get_start_line_number()
+ return vim.fn.line("'<")
+end
- return table.concat(selected_text, "\n")
+function visual_utils.get_end_line_number()
+ return vim.fn.line("'>")
+end
+
+function visual_utils.get_selected_lines()
+ return vim.fn.getline("'<", "'>")
+end
+
+function visual_utils.get_selected_text()
+ return table.concat(visual_utils.get_selected_lines(), "\n")
end
function visual_utils.get_selected_text_realtime()
diff --git a/lua/linux-x86_64generator.so b/lua/linux-x86_64generator.so
index 4252183..275c31c 100755
Binary files a/lua/linux-x86_64generator.so and b/lua/linux-x86_64generator.so differ
diff --git a/lua/mac-aarch64generator.so b/lua/mac-aarch64generator.so
index d6f512c..96f1be3 100755
Binary files a/lua/mac-aarch64generator.so and b/lua/mac-aarch64generator.so differ
diff --git a/lua/mac-x86_64generator.so b/lua/mac-x86_64generator.so
index c23f09a..6e988a5 100755
Binary files a/lua/mac-x86_64generator.so and b/lua/mac-x86_64generator.so differ
diff --git a/plugin/codesnap.lua b/plugin/codesnap.lua
index ab6ed18..845a9a8 100644
--- a/plugin/codesnap.lua
+++ b/plugin/codesnap.lua
@@ -22,3 +22,15 @@ end
vim.api.nvim_create_user_command("CodeSnap", take_snapshot(codesnap.copy_into_clipboard), { nargs = "*", range = "%" })
vim.api.nvim_create_user_command("CodeSnapSave", take_snapshot(codesnap.save_snapshot), { nargs = "*", range = "%" })
+
+vim.api.nvim_create_user_command(
+ "CodeSnapHighlight",
+ take_snapshot(codesnap.highlight_mode_copy_into_clipboard),
+ { nargs = "*", range = "%" }
+)
+
+vim.api.nvim_create_user_command(
+ "CodeSnapSaveHighlight",
+ take_snapshot(codesnap.highlight_mode_save_snapshot),
+ { nargs = "*", range = "%" }
+)
diff --git a/project.toml b/project.toml
index fe4409e..27ec611 100644
--- a/project.toml
+++ b/project.toml
@@ -1,6 +1,6 @@
[project]
name = "codesnap.nvim"
-version = "1.1.12"
+version = "1.3.1"
description = "📸 Snapshot plugin that can make pretty code snapshots with real-time previews for Neovim"
author = "Mist"
email = "mist.zzh@gmail.com"