https://github.com/chrisgrieser/nvim-scissors
Automagical editing and creation of snippets.
Science Score: 36.0%
This score indicates how likely this project is to be science-related based on various indicators:
-
○CITATION.cff file
-
✓codemeta.json file
Found codemeta.json file -
✓.zenodo.json file
Found .zenodo.json file -
○DOI references
-
✓Academic publication links
Links to: researchgate.net -
○Committers with academic emails
-
○Institutional organization owner
-
○JOSS paper metadata
-
○Scientific vocabulary similarity
Low similarity (9.2%) to scientific vocabulary
Keywords
Keywords from Contributors
Repository
Automagical editing and creation of snippets.
Basic Info
Statistics
- Stars: 532
- Watchers: 2
- Forks: 13
- Open Issues: 0
- Releases: 0
Topics
Metadata Files
README.md
nvim-scissors ✂️
Automagical editing and creation of snippets.
https://github.com/chrisgrieser/nvim-scissors/assets/73286100/c620958a-eef6-46c2-957a-8504733e0312
https://github.com/chrisgrieser/nvim-scissors/assets/73286100/de544b7e-20c3-4bec-b7aa-cbaaacca09ca
Table of contents
Features
- Add new snippets, edit snippets, or delete snippets on the fly.
- Syntax highlighting while you edit the snippet. Includes highlighting of
tabstops and placeholders such as
$0,${2:foobar}, or$CLIPBOARD - Automagical conversion from buffer text to JSON string.
- Intuitive UI for editing the snippet, dynamically adapting the number of prefixes.
- Automatic hot-reloading of any changes, so you do not have to restart nvim for changes to take effect.
- Optional JSON-formatting and sorting of the snippet file. (Useful when version-controlling your snippet collection.)
- Snippet/file selection via
telescope,snacks, orvim.ui.select. - Automatic bootstrapping of the snippet folder or new snippet files if needed.
- Supports only VSCode-style snippets.
[!TIP] You can use snippet-converter.nvim to convert your snippets to the VSCode format.
Rationale
- The VSCode snippet format is the closest thing to a standard regarding snippets. It is used by friendly-snippets and supported by most snippet engine plugins for nvim.
- However, VSCode snippets are stored as JSON, which are a pain to modify manually. This plugin alleviates that pain by automagically writing the JSON for you.
Requirements
- nvim 0.10+
- Snippets saved in the VSCode-style snippet format.
- Recommended: telescope
OR snacks.nvim. Without one of them,
the plugin falls back to
vim.ui.select, which still works but lacks search and snippet previews. - A snippet engine that can load VSCode-style snippets, such as:
- Optional: Treesitter parsers for the languages you want syntax highlighting for.
Installation
nvim-scissors
```lua -- lazy.nvim { "chrisgrieser/nvim-scissors", dependencies = "nvim-telescope/telescope.nvim", -- if using telescope opts = { snippetDir = "path/to/your/snippetFolder", } },
-- packer use { "chrisgrieser/nvim-scissors", dependencies = "nvim-telescope/telescope.nvim", -- if using telescope config = function() require("scissors").setup ({ snippetDir = "path/to/your/snippetFolder", }) end, } ```
Snippet engine setup
In addition, your snippet engine needs to point to the same snippet folder as
nvim-scissors:
[!TIP]
vim.fn.stdpath("config")returns the path to your nvim config.
LuaSnip
lua
require("luasnip.loaders.from_vscode").lazy_load {
paths = { "path/to/your/snippetFolder" },
}
mini.snippets
mini.snippets preferred snippet location is any snippets/ directory in the
runtimepath. For manually maintained snippets the best location is the user
config directory, which requires the following nvim-scissors setup:
lua
require("scissors").setup({
snippetDir = vim.fn.stdpath("config") .. "/snippets",
})
The mini.snippets setup requires explicit definition of loaders. Following its
Quickstart
guide should be enough to make it respect snippets from 'snippets/' directory
inside user config. Note: nvim-scissors works only with VSCode-style
snippet files (not Lua files or JSON arrays), and requires a
package.json for the VSCode
format.
blink.cmp
lua
require("blink.cmp").setup {
sources = {
providers = {
snippets = {
opts = {
search_paths = { "path/to/your/snippetFolder" },
},
}
}
}
}
It is recommended to use the latest release of blink.cmp for hot-reloading to
work.
basics-language-server
lua
require("lspconfig").basics_ls.setup({
settings = {
snippet = {
enable = true,
sources = { "path/to/your/snippetFolder" }
},
}
})
nvim-snippets
lua
require("nvim-snippets").setup {
search_paths = { "path/to/your/snippetFolder" },
}
vim-vsnip
lua
vim.g.vsnip_snippet_dir = "path/to/your/snippetFolder"
-- OR
vim.g.vsnip_snippet_dirs = { "path/to/your/snippetFolder" }
yasp.nvim
lua
require("yasp").setup {
paths = {
vim.fn.stdpath("config") .. "/snippets/package.json",
},
descs = { "user snippets" },
}
Usage
Starting nvim-scissors
The plugin provides two lua functions, .addNewSnippet() and .editSnippet():
```lua
vim.keymap.set(
"n",
"
-- when used in visual mode, prefills the selection as snippet body
vim.keymap.set(
{ "n", "x" },
"
You can also use :ScissorsAddNewSnippet and :ScissorsEditSnippet if you
prefer ex commands.
The :ScissorsAddSnippet ex command also accepts a range to prefill the snippet
body (for example :'<,'> ScissorsAddNewSnippet or :3 ScissorsAddNewSnippet).
Editing snippets in the popup window
The popup is just one window, so you can move between the prefix area and the
body with j and k or any other movement command. ("Prefix" is how trigger
words are referred to in the VSCode format.)
Use showHelp (default keymap: ?) to show a notification containing all
keymaps.
The popup intelligently adapts to changes in the prefix area: Each line represents one prefix, and creating or removing lines in that area thus changes the number of prefixes.
Configuration
The .setup() call is optional.
``lua
-- default settings
require("scissors").setup {
snippetDir = vim.fn.stdpath("config") .. "/snippets",
editSnippetPopup = {
height = 0.4, -- relative to the window, between 0-1
width = 0.6,
border = getBorder(), --vim.o.winborderon nvim 0.11, otherwise "rounded"
keymaps = {
-- if not mentioned otherwise, the keymaps apply to normal mode
cancel = "q",
saveChanges = "<CR>", -- alternatively, can also use:w`
goBackToSearch = "
snippetSelection = {
picker = "auto", ---@type "auto"|"telescope"|"snacks"|"vim.ui.select"
telescope = {
-- By default, the query only searches snippet prefixes. Set this to
-- `true` to also search the body of the snippets.
alsoSearchSnippetBody = false,
-- accepts the common telescope picker config
opts = {
layout_strategy = "horizontal",
layout_config = {
horizontal = { width = 0.9 },
preview_width = 0.6,
},
},
},
-- `snacks` picker configurable via snacks config,
-- see https://github.com/folke/snacks.nvim/blob/main/docs/picker.md
},
-- `none` writes as a minified json file using `vim.encode.json`.
-- `yq`/`jq` ensure formatted & sorted json files, which is relevant when
-- you version control your snippets. To use a custom formatter, set to a
-- list of strings, which will then be passed to `vim.system()`.
-- TIP: `jq` is already pre-installed on newer versions of macOS.
---@type "yq"|"jq"|"none"|string[]
jsonFormatter = "none",
backdrop = {
enabled = true,
blend = 50, -- between 0-100
},
icons = {
scissors = "",
},
} ```
Cookbook & FAQ
Introduction to the VSCode-style snippet format
This plugin requires that you have a valid VSCode snippet folder. In addition to
saving the snippets in the required JSON format, there must also be a
package.json file at the root of the snippet folder, specifying which files
should be used for which languages.
Example file structure inside the snippetDir:
txt
.
├── package.json
├── python.json
├── project-specific
│ └── nvim-lua.json
├── javascript.json
└── allFiletypes.json
Example package.json:
json
{
"contributes": {
"snippets": [
{
"language": "python",
"path": "./python.json"
},
{
"language": "lua",
"path": "./project-specific/nvim-lua.json"
},
{
"language": ["javascript", "typescript"],
"path": "./javascript.json"
},
{
"language": "all",
"path": "./allFiletypes.json"
}
]
},
"name": "my-snippets"
}
[!NOTE] The special filetype
allenables the snippets globally, regardless of filetype.
Example snippet file (here: nvim-lua.json):
json
{
"autocmd (Filetype)": {
"body": [
"vim.api.nvim_create_autocmd(\"FileType\", {",
"\tpattern = \"${1:ft}\",",
"\tcallback = function()",
"\t\t$0",
"\tend,",
"})"
],
"prefix": "autocmd (Filetype)"
},
"file exists": {
"body": "local fileExists = vim.uv.fs_stat(\"${1:filepath}\") ~= nil",
"prefix": "file exists"
},
}
For details, read the official VSCode snippet documentation:
- Snippet file specification
- package.json specification
- LuaSnip-specific additions to the format
Tabstops and variables
Tabstops
are denoted by $1, $2, $3, etc., with $0 being the last tabstop. They
support placeholders such as ${1:foobar}.
[!NOTE] Due to the use of
$in the snippet syntax, any literal$needs to be escaped as\$.
Furthermore, there are various variables you can use, such as $TM_FILENAME or
$LINE_COMMENT. See here for a full list of
variables.
friendly-snippets
Even though the snippets from the friendly-snippets
repository are written in the VSCode-style format, editing them directly is not
supported. The reason being that any changes made would be overwritten as soon
as the friendly-snippets repository is updated (which happens fairly
regularly). Unfortunately, there is little nvim-scissors can do about that.
What you can do, however, is to copy individual snippets files from the
friendly-snippets repository into your own snippet folder, and edit them there.
Edit snippet title or description
nvim-scissors only allows to edit the snippet prefix and snippet body, to keep
the UI as simple as possible. For the few cases where you need to edit a
snippet's title or description, you can use the openInFile keymap and edit
them directly in the snippet file.
Version controlling snippets & snippet file formatting
This plugin writes JSON files via vim.encode.json(). That method saves
the file in minified form and does not have a
deterministic order of dictionary keys.
Both, minification and unstable key order, are a problem if you
version-control your snippet collection. To solve this issue, nvim-scissors
lets you optionally unminify and sort the JSON files via yq or jq after
updating a snippet. (Both are also available via
mason.nvim.)
It is recommended to run yq/jq once on all files in your snippet collection,
since the first time you edit a file, you would still get a large diff from the
initial sorting. You can do so with yq using this command:
bash
cd "/your/snippet/dir"
find . -name "*.json" | xargs -I {} yq --inplace --output-format=json "sort_keys(..)" {}
How to do the same with jq is left as an exercise to the reader.
Snippets on visual selections (Luasnip only)
With Luasnip, this is an opt-in feature, enabled via:
lua
require("luasnip").setup {
store_selection_keys = "<Tab>",
}
In your VSCode-style snippet, use the token $TM_SELECTED_TEXT at the location
where you want the selection to be inserted. (It's roughly the equivalent of
LS_SELECT_RAW in the Luasnip syntax.)
Then, in visual mode, press the key from store_selection_keys. The selection
disappears, and you are put in insert mode. The next snippet you now trigger
is going to have $TM_SELECTED_TEXT replaced with your selection.
Auto-triggered snippets (Luasnip only)
While the VSCode snippet format does not support auto-triggered snippets,
LuaSnip allows you to specify auto-triggering in the VSCode-style JSON
files by adding the luasnip key.
nvim-scissors does not touch any keys other than prefix and body in the
JSON files, so any additions like the luasnip key are preserved.
[!TIP] You can use the
openInFilekeymap to directory open JSON file at the snippet's location to make edits there easier.
About the author
In my day job, I am a sociologist studying the social mechanisms underlying the digital economy. For my PhD project, I investigate the governance of the app economy and how software ecosystems manage the tension between innovation and compatibility. If you are interested in this subject, feel free to get in touch.
Owner
- Name: Chris Grieser
- Login: chrisgrieser
- Kind: user
- Location: Berlin, Germany
- Company: Technical University of Berlin
- Website: https://chris-grieser.de/
- Repositories: 189
- Profile: https://github.com/chrisgrieser
Researcher in sociology & software developer
GitHub Events
Total
- Issues event: 16
- Watch event: 137
- Delete event: 3
- Issue comment event: 46
- Push event: 126
- Pull request review event: 1
- Pull request review comment event: 1
- Pull request event: 21
- Fork event: 11
- Create event: 2
Last Year
- Issues event: 16
- Watch event: 137
- Delete event: 3
- Issue comment event: 46
- Push event: 126
- Pull request review event: 1
- Pull request review comment event: 1
- Pull request event: 21
- Fork event: 11
- Create event: 2
Committers
Last synced: 9 months ago
Top Committers
| Name | Commits | |
|---|---|---|
| Chris Grieser | 7****r | 435 |
| kraftnix | k****x@p****m | 2 |
| roycrippen4 | 5****4 | 1 |
| iguanacucumber | y****u@e****m | 1 |
| dependabot[bot] | 4****] | 1 |
| deatharte | 4****D | 1 |
| Zhanibek Adilbekov | z****v@p****e | 1 |
| Valentyn Makharynskyi | 1****k | 1 |
| Tim Harding | t****m@t****o | 1 |
| Evgeni Chasnovski | e****i@g****m | 1 |
| nickyhuyskens | n****s@m****m | 1 |
Committer Domains (Top 20 + Academic)
Issues and Pull Requests
Last synced: 6 months ago
All Time
- Total issues: 24
- Total pull requests: 21
- Average time to close issues: 16 days
- Average time to close pull requests: about 5 hours
- Total issue authors: 19
- Total pull request authors: 10
- Average comments per issue: 3.63
- Average comments per pull request: 1.38
- Merged pull requests: 17
- Bot issues: 1
- Bot pull requests: 3
Past Year
- Issues: 8
- Pull requests: 17
- Average time to close issues: about 5 hours
- Average time to close pull requests: about 6 hours
- Issue authors: 8
- Pull request authors: 6
- Average comments per issue: 2.5
- Average comments per pull request: 1.35
- Merged pull requests: 14
- Bot issues: 1
- Bot pull requests: 3
Top Authors
Issue Authors
- Rizhiy (3)
- ilan-schemoul (2)
- zolrath (2)
- MasouShizuka (2)
- garymh (1)
- roycrippen4 (1)
- schester44 (1)
- rogtino (1)
- echasnovski (1)
- pik4li (1)
- kraftnix (1)
- sweetbbak (1)
- NullVoxPopuli (1)
- mohamad-supangat (1)
- ofseed (1)
Pull Request Authors
- kraftnix (6)
- roesnera (2)
- DrKGD (2)
- valiank (2)
- nickyhuyskens (2)
- roycrippen4 (2)
- iguanacucumber (2)
- tim-harding (2)
- dependabot[bot] (2)
- liljaylj (2)
- echasnovski (1)
Top Labels
Issue Labels
Pull Request Labels
Dependencies
- actions/checkout v2 composite
- kdheepak/panvimdoc main composite
- stefanzweifel/git-auto-commit-action v4 composite
- actions/stale v8 composite
- JohnnyMorganz/stylua-action v2 composite
- actions/checkout v3 composite
- actions/checkout v4 composite
- stevearc/nvim-typecheck-action v2 composite
- amannn/action-semantic-pull-request v5 composite