fix conflicts
commit
856e44ec69
|
@ -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
|
|
@ -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: ''
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 3.0 MiB |
130
README.md
130
README.md
|
@ -4,19 +4,66 @@
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
|
|
||||||
<img src="https://img.shields.io/badge/Neovim-57A143?logo=neovim&logoColor=fff&style=for-the-badge" alt="Neovim" />
|
<img src="https://img.shields.io/badge/For Neovim 0.9+-57A143?logo=neovim&logoColor=fff&style=for-the-badge" alt="Neovim" />
|
||||||
|
|
||||||
<img src="https://img.shields.io/badge/Made%20With%20Lua-2C2D72?logo=lua&logoColor=fff&style=for-the-badge" alt="made with lua" >
|
|
||||||
|
|
||||||
<img src="https://img.shields.io/github/actions/workflow/status/mistricky/codesnap.nvim/release.yml?style=for-the-badge&label=release" alt="release action status" />
|
<img src="https://img.shields.io/github/actions/workflow/status/mistricky/codesnap.nvim/release.yml?style=for-the-badge&label=release" alt="release action status" />
|
||||||
|
|
||||||
<img src="https://img.shields.io/github/actions/workflow/status/mistricky/codesnap.nvim/lint.yml?style=for-the-badge&label=Lint" alt="release action status" />
|
<img src="https://img.shields.io/github/actions/workflow/status/mistricky/codesnap.nvim/lint.yml?style=for-the-badge&label=Lint" alt="release action status" />
|
||||||
|
|
||||||
|
<a href="https://github.com/mistricky/codesnap.nvim/issues">
|
||||||
|
<img alt="Issues" src="https://img.shields.io/github/issues/mistricky/codesnap.nvim?style=for-the-badge&logo=github&color=%23ffbd5e">
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/mistricky/codesnap.nvim/blob/main/LICENSE">
|
||||||
|
<img alt="License" src="https://img.shields.io/github/license/mistricky/codesnap.nvim?style=for-the-badge&logo=github&color=%235ef1ff">
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/mistricky/codesnap.nvim/stars">
|
||||||
|
<img alt="stars" src="https://img.shields.io/github/stars/mistricky/codesnap.nvim?style=for-the-badge&logo=github&color=%23bd5eff">
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<img src="https://img.shields.io/badge/Made%20With%20Lua-2C2D72?logo=lua&logoColor=fff&style=for-the-badge" alt="made with lua" >
|
||||||
|
|
||||||
|
<img src="https://img.shields.io/badge/Written%20in%20Rust-B7410E?logo=rust&logoColor=fff&style=for-the-badge" alt="written in rust" >
|
||||||
|
|
||||||
|
<a href="https://dotfyle.com/plugins/mistricky/codesnap.nvim">
|
||||||
|
<img src="https://dotfyle.com/plugins/mistricky/codesnap.nvim/shield?style=for-the-badge" />
|
||||||
|
</a>
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h1 align="center">CodeSnap.nvim</h1>
|
<h1 align="center">CodeSnap.nvim</h1>
|
||||||
<p align="center">📸 Snapshot plugin with rich features that can make pretty code snapshots for Neovim</p>
|
<p align="center">📸 Snapshot plugin with rich features that can make pretty code snapshots for Neovim</p>
|
||||||
|
|
||||||
|
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||||
|
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||||
|
|
||||||
|
- [🚣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)
|
||||||
|
|
||||||
|
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||||
|
|
||||||
## 🚣Migration
|
## 🚣Migration
|
||||||
If you have installed v0.x before, this chapter will show you what break changes version v1.x introduced.
|
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
|
- 🤖 Generate snapshots using only a single command
|
||||||
- 🍞 Breadcrumbs for display file path
|
- 🍞 Breadcrumbs for display file path
|
||||||
- 🌊 More beautiful background theme
|
- 🌊 More beautiful background theme
|
||||||
- 🔢 [WIP] Column number
|
- 🔢 Support for display line number make sharing code snapshot easier
|
||||||
|
|
||||||
## Prerequirements
|
## Prerequirements
|
||||||
- Neovim 0.9.0+
|
- 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
|
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 = {
|
||||||
|
{ "<leader>cc", "<cmd>CodeSnap<cr>", mode = "x", desc = "Save selected code snapshot into clipboard" },
|
||||||
|
{ "<leader>cs", "<cmd>CodeSnapSave<cr>", mode = "x", desc = "Save selected code snapshot in ~/Pictures" },
|
||||||
|
},
|
||||||
|
opts = {
|
||||||
|
save_path = "~/Pictures",
|
||||||
|
has_breadcrumbs = true,
|
||||||
|
bg_theme = "bamboo",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
`CodeSnap.nvim` provides the following two ways to take snapshots of currently selected code
|
`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
|
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
|
### 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.
|
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:
|
The breadcrumbs look like:
|
||||||
![image](https://github.com/mistricky/codesnap.nvim/assets/22574136/23274faa-36a9-4d41-88a5-e48c44b4d5bf)
|
![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
|
### 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:
|
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
|
```lua
|
||||||
|
@ -157,6 +251,17 @@ require("codesnap").setup({
|
||||||
![image](https://github.com/mistricky/codesnap.nvim/assets/22574136/84b80d0f-1467-4bdf-9cbd-aede868f93aa)
|
![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
|
## 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:
|
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
|
CodeSnapSave # Save the snapshot of the currently selected code and save it on the disk
|
||||||
```
|
```
|
||||||
|
**Lua**
|
||||||
|
```lua
|
||||||
|
local codesnap <const> = 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
|
## Configuration
|
||||||
Define your custom config using `setup` function
|
Define your custom config using `setup` function
|
||||||
|
@ -254,6 +369,8 @@ There is a default config:
|
||||||
bg_theme = "default",
|
bg_theme = "default",
|
||||||
breadcrumbs_separator = "/",
|
breadcrumbs_separator = "/",
|
||||||
has_breadcrumbs = false,
|
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).
|
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.
|
||||||
|
|
||||||
|
<img src="CONTRIBUTORS.svg" />
|
||||||
|
|
||||||
## License
|
## License
|
||||||
MIT.
|
MIT.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
**codesnap.nvim** 📸 Snapshot plugin that can make pretty code snapshots with real-time previews for Neovim
|
**codesnap.nvim** 📸 Snapshot plugin that can make pretty code snapshots with real-time previews for Neovim
|
||||||
|
|
||||||
Author: Mist <mist.zzh@gmail.com>
|
Author: Mist <mist.zzh@gmail.com>
|
||||||
version: 1.1.12
|
version: 1.3.1
|
||||||
|
|
|
@ -8,6 +8,18 @@ version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
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]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "1.1.2"
|
version = "1.1.2"
|
||||||
|
@ -17,6 +29,12 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "allocator-api2"
|
||||||
|
version = "0.2.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arboard"
|
name = "arboard"
|
||||||
version = "3.3.2"
|
version = "3.3.2"
|
||||||
|
@ -87,7 +105,7 @@ dependencies = [
|
||||||
"regex",
|
"regex",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"shlex",
|
"shlex",
|
||||||
"syn",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -120,6 +138,39 @@ version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
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]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.90"
|
version = "1.0.90"
|
||||||
|
@ -245,6 +296,41 @@ dependencies = [
|
||||||
"cfg-if",
|
"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]]
|
[[package]]
|
||||||
name = "deranged"
|
name = "deranged"
|
||||||
version = "0.3.11"
|
version = "0.3.11"
|
||||||
|
@ -262,7 +348,7 @@ checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -386,7 +472,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -400,6 +486,7 @@ name = "generator"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arboard",
|
"arboard",
|
||||||
|
"cached",
|
||||||
"cosmic-text",
|
"cosmic-text",
|
||||||
"nvim-oxi",
|
"nvim-oxi",
|
||||||
"regex",
|
"regex",
|
||||||
|
@ -433,6 +520,10 @@ name = "hashbrown"
|
||||||
version = "0.14.3"
|
version = "0.14.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
|
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
"allocator-api2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "home"
|
name = "home"
|
||||||
|
@ -443,6 +534,12 @@ dependencies = [
|
||||||
"windows-sys 0.52.0",
|
"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]]
|
[[package]]
|
||||||
name = "image"
|
name = "image"
|
||||||
version = "0.24.9"
|
version = "0.24.9"
|
||||||
|
@ -467,6 +564,15 @@ dependencies = [
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "instant"
|
||||||
|
version = "0.1.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.10"
|
version = "1.0.10"
|
||||||
|
@ -762,7 +868,7 @@ checksum = "7fa77de5791207f41bab307dadb91e66a2bbbd19433e4243ef98c9d45e03a007"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1033,7 +1139,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1055,7 +1161,7 @@ checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1091,6 +1197,12 @@ version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
|
checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "swash"
|
name = "swash"
|
||||||
version = "0.1.12"
|
version = "0.1.12"
|
||||||
|
@ -1102,6 +1214,17 @@ dependencies = [
|
||||||
"zeno",
|
"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]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.52"
|
version = "2.0.52"
|
||||||
|
@ -1183,7 +1306,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.52",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1669,3 +1792,23 @@ name = "zeno"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dd15f8e0dbb966fd9245e7498c7e9e5055d9e5c8b676b95bd67091cd11a1e697"
|
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",
|
||||||
|
]
|
||||||
|
|
|
@ -13,6 +13,7 @@ arboard = {features = ["wayland-data-control"], version = "3.3.2"}
|
||||||
thiserror = "1.0.58"
|
thiserror = "1.0.58"
|
||||||
regex = "1.10.3"
|
regex = "1.10.3"
|
||||||
two-face = "0.3.0"
|
two-face = "0.3.0"
|
||||||
|
cached = "0.49.3"
|
||||||
wsl = "0.1.0"
|
wsl = "0.1.0"
|
||||||
sys-info = "0.9.1"
|
sys-info = "0.9.1"
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
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 {
|
||||||
|
@ -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) {
|
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();
|
||||||
|
@ -34,29 +39,33 @@ fn replace_tab_to_space(text: &str) -> String {
|
||||||
str::replace(text, "\t", &spaces)
|
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 {
|
fn trim_space(text: &str) -> String {
|
||||||
let lines = text.split("\n").collect::<Vec<&str>>();
|
let lines = text.split("\n").collect::<Vec<&str>>();
|
||||||
let first_line = lines.first().unwrap();
|
let regex = Regex::new(r"(?:^|\n)(\s*)").unwrap();
|
||||||
let head_spaces = Regex::new(r"^(\s*)").unwrap().find(first_line);
|
let captures_iter = regex.captures_iter(text);
|
||||||
|
let space_lengths = captures_iter
|
||||||
|
.map(|capture| capture.get(1).unwrap().as_str().len())
|
||||||
|
.collect::<Vec<usize>>();
|
||||||
|
|
||||||
match head_spaces {
|
if space_lengths.len() < lines.len() {
|
||||||
Some(head_spaces) => {
|
return text.to_string();
|
||||||
return lines
|
}
|
||||||
|
|
||||||
|
let need_to_remove_spaces = " ".repeat(space_lengths.into_iter().min().unwrap());
|
||||||
|
|
||||||
|
lines
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|line| {
|
.map(|line| {
|
||||||
Regex::new(format!("^{}", head_spaces.as_str()).as_ref())
|
Regex::new(format!("^{}", need_to_remove_spaces).as_ref())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.replace(line, "")
|
.replace(line, "")
|
||||||
.to_string()
|
.to_string()
|
||||||
})
|
})
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join("\n");
|
.join("\n")
|
||||||
}
|
|
||||||
None => text.to_string(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prepare_code(code: &str) -> String {
|
pub fn prepare_code(code: &str) -> String {
|
||||||
replace_tab_to_space(&trim_space(&code))
|
trim_space(&replace_tab_to_space(&code))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
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 highlight_code_block;
|
||||||
pub mod interface;
|
pub mod interface;
|
||||||
|
pub mod line_number;
|
||||||
pub mod rect;
|
pub mod rect;
|
||||||
pub mod watermark;
|
pub mod watermark;
|
||||||
|
|
|
@ -35,6 +35,7 @@ impl Component for Background {
|
||||||
context: &ComponentContext,
|
context: &ComponentContext,
|
||||||
_render_params: &RenderParams,
|
_render_params: &RenderParams,
|
||||||
_style: &ComponentStyle,
|
_style: &ComponentStyle,
|
||||||
|
_parent_style: &ComponentStyle,
|
||||||
) -> render_error::Result<()> {
|
) -> render_error::Result<()> {
|
||||||
let mut paint = Paint::default();
|
let mut paint = Paint::default();
|
||||||
let w = pixmap.width() as f32;
|
let w = pixmap.width() as f32;
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::{code::calc_wh, edges::margin::Margin, text::FontRenderer};
|
||||||
|
|
||||||
use super::interface::{
|
use super::interface::{
|
||||||
component::Component,
|
component::Component,
|
||||||
style::{RawComponentStyle, Size},
|
style::{ComponentStyle, RawComponentStyle, Size},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Breadcrumbs {
|
pub struct Breadcrumbs {
|
||||||
|
@ -41,6 +41,7 @@ impl Component for Breadcrumbs {
|
||||||
context: &super::interface::component::ComponentContext,
|
context: &super::interface::component::ComponentContext,
|
||||||
render_params: &super::interface::component::RenderParams,
|
render_params: &super::interface::component::RenderParams,
|
||||||
style: &super::interface::style::ComponentStyle,
|
style: &super::interface::style::ComponentStyle,
|
||||||
|
_parent_style: &ComponentStyle,
|
||||||
) -> super::interface::render_error::Result<()> {
|
) -> super::interface::render_error::Result<()> {
|
||||||
if self.has_breadcrumbs {
|
if self.has_breadcrumbs {
|
||||||
let attrs = Attrs::new()
|
let attrs = Attrs::new()
|
||||||
|
|
|
@ -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::{
|
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(
|
||||||
|
@ -39,6 +33,7 @@ impl Component for Code {
|
||||||
context: &ComponentContext,
|
context: &ComponentContext,
|
||||||
render_params: &RenderParams,
|
render_params: &RenderParams,
|
||||||
style: &ComponentStyle,
|
style: &ComponentStyle,
|
||||||
|
_parent_style: &ComponentStyle,
|
||||||
) -> render_error::Result<()> {
|
) -> render_error::Result<()> {
|
||||||
let params = &context.take_snapshot_params;
|
let params = &context.take_snapshot_params;
|
||||||
let highlight = Highlight::new(
|
let highlight = Highlight::new(
|
||||||
|
|
|
@ -33,6 +33,7 @@ impl Component for MacTitleBar {
|
||||||
context: &ComponentContext,
|
context: &ComponentContext,
|
||||||
render_params: &RenderParams,
|
render_params: &RenderParams,
|
||||||
_style: &ComponentStyle,
|
_style: &ComponentStyle,
|
||||||
|
_parent_style: &ComponentStyle,
|
||||||
) -> render_error::Result<()> {
|
) -> render_error::Result<()> {
|
||||||
self.draw_control_buttons(
|
self.draw_control_buttons(
|
||||||
// Control bar construct by draw circles, after drawn, the path will be at the center,
|
// Control bar construct by draw circles, after drawn, the path will be at the center,
|
||||||
|
|
|
@ -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<Box<dyn Component>>,
|
||||||
|
line_height: f32,
|
||||||
|
start_line_number: usize,
|
||||||
|
end_line_number: usize,
|
||||||
|
render_condition: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component for HighlightCodeBlock {
|
||||||
|
fn children(&self) -> &Vec<Box<dyn Component>> {
|
||||||
|
&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<usize>,
|
||||||
|
end_line_number: Option<usize>,
|
||||||
|
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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +1,10 @@
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use tiny_skia::Pixmap;
|
|
||||||
|
|
||||||
use crate::{config::TakeSnapshotParams, edges::edge::Edge};
|
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
render_error,
|
render_error,
|
||||||
style::{ComponentAlign, ComponentStyle, RawComponentStyle, Size, Style},
|
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 struct ComponentContext {
|
||||||
pub scale_factor: f32,
|
pub scale_factor: f32,
|
||||||
|
@ -73,6 +70,7 @@ pub trait Component {
|
||||||
_context: &ComponentContext,
|
_context: &ComponentContext,
|
||||||
_render_params: &RenderParams,
|
_render_params: &RenderParams,
|
||||||
_style: &ComponentStyle,
|
_style: &ComponentStyle,
|
||||||
|
_parent_style: &ComponentStyle,
|
||||||
) -> render_error::Result<()> {
|
) -> render_error::Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -91,11 +89,17 @@ pub trait Component {
|
||||||
fn parsed_style(&self) -> Style<f32> {
|
fn parsed_style(&self) -> Style<f32> {
|
||||||
let style = self.style();
|
let style = self.style();
|
||||||
let (width, height) = self.get_dynamic_wh();
|
let (width, height) = self.get_dynamic_wh();
|
||||||
|
let width = self.parse_size(style.width, width)
|
||||||
|
+ style.padding.horizontal()
|
||||||
|
+ style.margin.horizontal();
|
||||||
|
|
||||||
Style {
|
Style {
|
||||||
width: self.parse_size(style.width, width)
|
min_width: style.min_width,
|
||||||
+ style.padding.horizontal()
|
width: if width > style.min_width {
|
||||||
+ style.margin.horizontal(),
|
width
|
||||||
|
} else {
|
||||||
|
style.min_width
|
||||||
|
},
|
||||||
height: self.parse_size(style.height, height)
|
height: self.parse_size(style.height, height)
|
||||||
+ style.padding.vertical()
|
+ style.padding.vertical()
|
||||||
+ style.margin.vertical(),
|
+ style.margin.vertical(),
|
||||||
|
@ -116,13 +120,13 @@ pub trait Component {
|
||||||
let style = self.parsed_style();
|
let style = self.parsed_style();
|
||||||
let render_params = self.initialize(
|
let render_params = self.initialize(
|
||||||
&component_render_params.parse_into_render_params_with_style(
|
&component_render_params.parse_into_render_params_with_style(
|
||||||
parent_style,
|
parent_style.clone(),
|
||||||
sibling_style,
|
sibling_style,
|
||||||
style.clone(),
|
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 children = self.children();
|
||||||
let mut sibling_render_params = RenderParams {
|
let mut sibling_render_params = RenderParams {
|
||||||
|
@ -152,6 +156,8 @@ pub trait Component {
|
||||||
Ok(render_params.clone())
|
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) {
|
fn get_dynamic_wh(&self) -> (f32, f32) {
|
||||||
let children = self.children();
|
let children = self.children();
|
||||||
let calc_children_wh = |cb: fn((f32, f32), &Box<dyn Component>) -> (f32, f32)| {
|
let calc_children_wh = |cb: fn((f32, f32), &Box<dyn Component>) -> (f32, f32)| {
|
||||||
|
@ -160,11 +166,13 @@ pub trait Component {
|
||||||
let style = self.style();
|
let style = self.style();
|
||||||
|
|
||||||
match style.align {
|
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| {
|
ComponentAlign::Row => calc_children_wh(|(w, h), child| {
|
||||||
let style = child.parsed_style();
|
let style = child.parsed_style();
|
||||||
|
|
||||||
(w + style.width, h.max(style.height))
|
(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| {
|
ComponentAlign::Column => calc_children_wh(|(w, h), child| {
|
||||||
let style = child.parsed_style();
|
let style = child.parsed_style();
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ pub enum Size {
|
||||||
pub struct Style<T> {
|
pub struct Style<T> {
|
||||||
pub width: T,
|
pub width: T,
|
||||||
pub height: T,
|
pub height: T,
|
||||||
|
pub min_width: f32,
|
||||||
pub align: ComponentAlign,
|
pub align: ComponentAlign,
|
||||||
pub padding: Padding,
|
pub padding: Padding,
|
||||||
pub margin: Margin,
|
pub margin: Margin,
|
||||||
|
@ -26,6 +27,7 @@ pub type ComponentStyle = Style<f32>;
|
||||||
impl Default for RawComponentStyle {
|
impl Default for RawComponentStyle {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Style {
|
Style {
|
||||||
|
min_width: 0.,
|
||||||
width: Size::Dynamic,
|
width: Size::Dynamic,
|
||||||
height: Size::Dynamic,
|
height: Size::Dynamic,
|
||||||
align: ComponentAlign::Row,
|
align: ComponentAlign::Row,
|
||||||
|
@ -38,6 +40,7 @@ impl Default for RawComponentStyle {
|
||||||
impl Default for ComponentStyle {
|
impl Default for ComponentStyle {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Style {
|
Style {
|
||||||
|
min_width: 0.,
|
||||||
width: 0.,
|
width: 0.,
|
||||||
height: 0.,
|
height: 0.,
|
||||||
align: ComponentAlign::Row,
|
align: ComponentAlign::Row,
|
||||||
|
@ -54,6 +57,12 @@ impl RawComponentStyle {
|
||||||
self
|
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 {
|
pub fn align(mut self, align: ComponentAlign) -> Self {
|
||||||
self.align = align;
|
self.align = align;
|
||||||
self
|
self
|
||||||
|
|
|
@ -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<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,
|
||||||
|
_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<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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,14 +1,16 @@
|
||||||
use crate::edges::padding::Padding;
|
|
||||||
|
|
||||||
use super::interface::{
|
use super::interface::{
|
||||||
component::{Component, ComponentContext, RenderParams},
|
component::{Component, ComponentContext, RenderParams},
|
||||||
render_error,
|
render_error,
|
||||||
style::{ComponentAlign, ComponentStyle, RawComponentStyle, Style},
|
style::{ComponentAlign, ComponentStyle, RawComponentStyle, Style},
|
||||||
};
|
};
|
||||||
|
use crate::edges::padding::Padding;
|
||||||
use tiny_skia::{FillRule, Paint, PathBuilder, Pixmap, Transform};
|
use tiny_skia::{FillRule, Paint, PathBuilder, Pixmap, Transform};
|
||||||
|
|
||||||
|
pub const EDITOR_PADDING: f32 = 20.;
|
||||||
|
|
||||||
pub struct Rect {
|
pub struct Rect {
|
||||||
radius: f32,
|
radius: f32,
|
||||||
|
min_width: f32,
|
||||||
children: Vec<Box<dyn Component>>,
|
children: Vec<Box<dyn Component>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,8 +21,9 @@ impl Component for Rect {
|
||||||
|
|
||||||
fn style(&self) -> RawComponentStyle {
|
fn style(&self) -> RawComponentStyle {
|
||||||
Style::default()
|
Style::default()
|
||||||
|
.min_width(self.min_width)
|
||||||
.align(ComponentAlign::Column)
|
.align(ComponentAlign::Column)
|
||||||
.padding(Padding::from_value(20.))
|
.padding(Padding::from_value(EDITOR_PADDING))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_self(
|
fn draw_self(
|
||||||
|
@ -29,6 +32,7 @@ impl Component for Rect {
|
||||||
context: &ComponentContext,
|
context: &ComponentContext,
|
||||||
render_params: &RenderParams,
|
render_params: &RenderParams,
|
||||||
style: &ComponentStyle,
|
style: &ComponentStyle,
|
||||||
|
_parent_style: &ComponentStyle,
|
||||||
) -> render_error::Result<()> {
|
) -> render_error::Result<()> {
|
||||||
let mut path_builder = PathBuilder::new();
|
let mut path_builder = PathBuilder::new();
|
||||||
let x = render_params.x;
|
let x = render_params.x;
|
||||||
|
@ -92,7 +96,11 @@ impl Component for Rect {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rect {
|
impl Rect {
|
||||||
pub fn new(radius: f32, children: Vec<Box<dyn Component>>) -> Rect {
|
pub fn new(radius: f32, min_width: Option<f32>, children: Vec<Box<dyn Component>>) -> Rect {
|
||||||
Rect { radius, children }
|
Rect {
|
||||||
|
radius,
|
||||||
|
children,
|
||||||
|
min_width: min_width.unwrap_or(0.),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ impl Component for Watermark {
|
||||||
context: &ComponentContext,
|
context: &ComponentContext,
|
||||||
render_params: &RenderParams,
|
render_params: &RenderParams,
|
||||||
_style: &ComponentStyle,
|
_style: &ComponentStyle,
|
||||||
|
_parent_style: &ComponentStyle,
|
||||||
) -> render_error::Result<()> {
|
) -> render_error::Result<()> {
|
||||||
let params = &context.take_snapshot_params;
|
let params = &context.take_snapshot_params;
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,10 @@ 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>,
|
||||||
|
pub highlight_start_line_number: Option<usize>,
|
||||||
|
pub highlight_end_line_number: Option<usize>,
|
||||||
|
pub min_width: Option<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromObject for TakeSnapshotParams {
|
impl FromObject for TakeSnapshotParams {
|
||||||
|
|
|
@ -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 "<php" tag
|
||||||
|
// Should use PHP Source as highlight language if the source content not contains "<php" tag
|
||||||
if let Some(identifier) = self.highlighting_language_source_map.get(&syntax.name[..]) {
|
if let Some(identifier) = self.highlighting_language_source_map.get(&syntax.name[..]) {
|
||||||
if !self.content.contains(identifier) {
|
if !self.content.contains(identifier) {
|
||||||
return Ok(syntax_set
|
return Ok(syntax_set
|
||||||
|
@ -77,11 +80,14 @@ impl Highlight {
|
||||||
let mut highlight = HighlightLines::new(syntax, &theme_set.themes[theme]);
|
let mut highlight = HighlightLines::new(syntax, &theme_set.themes[theme]);
|
||||||
let attrs = Attrs::new().family(Family::Name(self.font_family.as_ref()));
|
let attrs = Attrs::new().family(Family::Name(self.font_family.as_ref()));
|
||||||
|
|
||||||
|
// Highlight the content line by line using highlight_line function
|
||||||
Ok(LinesWithEndings::from(&self.content)
|
Ok(LinesWithEndings::from(&self.content)
|
||||||
.map(|line| highlight.highlight_line(line, &syntax_set).unwrap())
|
.map(|line| {
|
||||||
.fold(vec![], |acc, cur| [acc, cur].concat())
|
highlight
|
||||||
|
.highlight_line(line, &syntax_set)
|
||||||
|
.unwrap()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(move |(style, str)| {
|
.map(|(style, str)| {
|
||||||
let syntect::highlighting::Color { r, g, b, a: _ } = style.foreground;
|
let syntect::highlighting::Color { r, g, b, a: _ } = style.foreground;
|
||||||
let attrs = match style.font_style {
|
let attrs = match style.font_style {
|
||||||
FontStyle::BOLD => attrs.weight(Weight::BOLD),
|
FontStyle::BOLD => attrs.weight(Weight::BOLD),
|
||||||
|
@ -92,6 +98,10 @@ impl Highlight {
|
||||||
|
|
||||||
(str, attrs.color(cosmic_text::Color::rgb(r, g, b)))
|
(str, attrs.color(cosmic_text::Color::rgb(r, g, b)))
|
||||||
})
|
})
|
||||||
|
.collect::<HighlightResult>()
|
||||||
|
})
|
||||||
|
.fold(vec![], |acc, cur| [acc, cur].concat())
|
||||||
|
.into_iter()
|
||||||
.collect::<HighlightResult>())
|
.collect::<HighlightResult>())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,17 +4,21 @@ 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::highlight_code_block::HighlightCodeBlock;
|
||||||
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;
|
||||||
|
|
||||||
// Scale the screenshot to 3 times its size
|
// Scale the screenshot to 3 times its size
|
||||||
const SCALE_FACTOR: f32 = 3.;
|
const SCALE_FACTOR: f32 = 3.;
|
||||||
|
const LINE_HEIGHT: f32 = 20.;
|
||||||
|
|
||||||
// The params is come from neovim instance
|
// The params is come from neovim instance
|
||||||
pub fn take_snapshot(params: TakeSnapshotParams) -> render_error::Result<Pixmap> {
|
pub fn take_snapshot(params: TakeSnapshotParams) -> render_error::Result<Pixmap> {
|
||||||
|
@ -25,6 +29,7 @@ pub fn take_snapshot(params: TakeSnapshotParams) -> render_error::Result<Pixmap>
|
||||||
let pixmap = Container::from_children(vec![Box::new(Background::from_children(vec![
|
let pixmap = Container::from_children(vec![Box::new(Background::from_children(vec![
|
||||||
Box::new(Rect::new(
|
Box::new(Rect::new(
|
||||||
16.,
|
16.,
|
||||||
|
params.min_width,
|
||||||
vec![
|
vec![
|
||||||
Box::new(MacTitleBar::from_radius(8., params.mac_window_bar)),
|
Box::new(MacTitleBar::from_radius(8., params.mac_window_bar)),
|
||||||
Box::new(Breadcrumbs::from_path(
|
Box::new(Breadcrumbs::from_path(
|
||||||
|
@ -33,7 +38,19 @@ 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(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)),
|
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
|
|
|
@ -25,8 +25,15 @@ local function parse_save_path(save_path)
|
||||||
return parsed_save_path .. auto_generate_snap_filename()
|
return parsed_save_path .. auto_generate_snap_filename()
|
||||||
end
|
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)
|
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)
|
||||||
|
@ -40,7 +47,8 @@ function config_module.get_config(extension)
|
||||||
fonts_folder = assets_folder .. "/fonts",
|
fonts_folder = assets_folder .. "/fonts",
|
||||||
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 get_file_path(static.config.show_workspace) 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)
|
||||||
|
|
|
@ -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<CR>", {})
|
||||||
|
vim.api.nvim_buf_set_keymap(bufnr, "", "<ESC>", ":q<CR>", {})
|
||||||
|
vim.api.nvim_buf_set_keymap(
|
||||||
|
bufnr,
|
||||||
|
"v",
|
||||||
|
"<CR>",
|
||||||
|
":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())<CR>",
|
||||||
|
{ silent = true }
|
||||||
|
)
|
||||||
|
vim.api.nvim_set_current_win(window_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
return highlight_module
|
|
@ -1,24 +1,27 @@
|
||||||
local static = require("codesnap.static")
|
local static = require("codesnap.static")
|
||||||
|
local visual_utils = require("codesnap.utils.visual")
|
||||||
local table_utils = require("codesnap.utils.table")
|
local table_utils = require("codesnap.utils.table")
|
||||||
local string_utils = require("codesnap.utils.string")
|
local string_utils = require("codesnap.utils.string")
|
||||||
local config_module = require("codesnap.config")
|
local config_module = require("codesnap.config")
|
||||||
|
local highlight_module = require("codesnap.highlight")
|
||||||
|
|
||||||
local main = {
|
local main = {
|
||||||
cwd = static.cwd,
|
cwd = static.cwd,
|
||||||
preview_switch = static.preview_switch,
|
preview_switch = static.preview_switch,
|
||||||
|
highlight_mode_config = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
function main.setup(config)
|
function main.setup(config)
|
||||||
static.config = table_utils.merge(static.config, config == nil and {} or config)
|
static.config = table_utils.merge(static.config, config == nil and {} or config)
|
||||||
end
|
end
|
||||||
|
|
||||||
function main.copy_into_clipboard(extension)
|
function main.copy_into_clipboard_with_config(config)
|
||||||
require("generator").copy_into_clipboard(config_module.get_config(extension))
|
require("generator").copy_into_clipboard(config)
|
||||||
vim.cmd("delmarks <>")
|
vim.cmd("delmarks <>")
|
||||||
vim.notify("Save snapshot into clipboard successfully")
|
vim.notify("Save snapshot into clipboard successfully")
|
||||||
end
|
end
|
||||||
|
|
||||||
function main.save_snapshot(extension)
|
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(
|
||||||
"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",
|
"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)
|
error("The extension of save_path should be .png", 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
local config = config_module.get_config(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
|
||||||
|
|
||||||
|
-- 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
|
return main
|
||||||
|
|
|
@ -10,6 +10,9 @@ return {
|
||||||
bg_theme = "default",
|
bg_theme = "default",
|
||||||
breadcrumbs_separator = "/",
|
breadcrumbs_separator = "/",
|
||||||
has_breadcrumbs = false,
|
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("(.*[/\\])"))),
|
cwd = path_utils.back(path_utils.back(debug.getinfo(1, "S").source:sub(2):match("(.*[/\\])"))),
|
||||||
preview_switch = true,
|
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
|
|
|
@ -1,17 +1,29 @@
|
||||||
local string_utils = require("codesnap.utils.string")
|
local string_utils = require("codesnap.utils.string")
|
||||||
local path_utils = {}
|
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)
|
function path_utils.back(path)
|
||||||
local parsed_path, _ = path:gsub("/[^\\/]+/?$", "")
|
local parsed_path, _ = path:gsub("/[^\\/]+/?$", "")
|
||||||
|
|
||||||
return parsed_path
|
return parsed_path
|
||||||
end
|
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()
|
function path_utils.get_relative_path()
|
||||||
local full_file_path = vim.fn.expand("%:p")
|
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
|
end
|
||||||
|
|
||||||
return path_utils
|
return path_utils
|
||||||
|
|
|
@ -24,4 +24,14 @@ function string_util.convert_empty_to_nil(target)
|
||||||
end
|
end
|
||||||
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
|
return string_util
|
||||||
|
|
|
@ -33,7 +33,7 @@ end
|
||||||
|
|
||||||
function table_utils.serialize_array(t)
|
function table_utils.serialize_array(t)
|
||||||
local result = list_utils.map(t, function(ele)
|
local result = list_utils.map(t, function(ele)
|
||||||
table_utils.serialize_json(ele)
|
table_utils.to_string(ele)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
return "[" .. result.concat(t, ",") .. "]"
|
return "[" .. result.concat(t, ",") .. "]"
|
||||||
|
@ -43,17 +43,17 @@ function table_utils.serialize_table(t)
|
||||||
local result = {}
|
local result = {}
|
||||||
|
|
||||||
for key, value in pairs(t) do
|
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
|
end
|
||||||
|
|
||||||
return "{" .. table.concat(result, ",") .. "}"
|
return "{" .. table.concat(result, ",") .. "}"
|
||||||
end
|
end
|
||||||
|
|
||||||
function table_utils.serialize_string(value)
|
function table_utils.serialize_string(value)
|
||||||
return '"' .. value .. '"'
|
return "[[" .. value .. "]]"
|
||||||
end
|
end
|
||||||
|
|
||||||
function table_utils.serialize_json(t)
|
function table_utils.to_string(t)
|
||||||
local complex_type_parser = {
|
local complex_type_parser = {
|
||||||
array = table_utils.serialize_array,
|
array = table_utils.serialize_array,
|
||||||
table = table_utils.serialize_table,
|
table = table_utils.serialize_table,
|
||||||
|
@ -67,4 +67,14 @@ function table_utils.serialize_json(t)
|
||||||
return parse(t)
|
return parse(t)
|
||||||
end
|
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
|
return table_utils
|
||||||
|
|
|
@ -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,10 +14,20 @@ local function get_whole_lines(from, to)
|
||||||
return table.concat(lines, "\n")
|
return table.concat(lines, "\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
function visual_utils.get_selected_text()
|
function visual_utils.get_start_line_number()
|
||||||
local selected_text = vim.fn.getline("'<", "'>")
|
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
|
end
|
||||||
|
|
||||||
function visual_utils.get_selected_text_realtime()
|
function visual_utils.get_selected_text_realtime()
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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("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("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 = "%" }
|
||||||
|
)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[project]
|
[project]
|
||||||
name = "codesnap.nvim"
|
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"
|
description = "📸 Snapshot plugin that can make pretty code snapshots with real-time previews for Neovim"
|
||||||
author = "Mist"
|
author = "Mist"
|
||||||
email = "mist.zzh@gmail.com"
|
email = "mist.zzh@gmail.com"
|
||||||
|
|
Loading…
Reference in New Issue