Code Monkey home page Code Monkey logo

kakoune-snippets's Introduction

kakoune-snippets

Disclaimer: I've recently downsized the plugin and removed functionality. This is both for making the plugin more manageable, and so that I actually want to use and work on it. If you are interested in using (or forking) this previous state, you have my blessing (not that you need it). The latest commit of this state is 9c96e64a567ae5cb16d47cf9d3a56189f77c430c.

(Yet another) kakoune plugin for handling snippets.

demo

Setup

Add snippets.kak to your autoload dir: ~/.config/kak/autoload/, or source it manually.

This plugin requires the kakoune version 2022.10.31.

Usage

The extension is configured via two options:

  • snippets [str-list] is a list of {name, trigger, command} tuples. The name is the identifier of the snippet, the trigger is a short string that identifies the snippet, and the command is what gets eval'd when the snippet is activated. In practice it's just a flat list that looks like snip1-name snip1-trigger snip1-command snip2-name snip2-trigger snip2-command...
  • snippets_auto_expand [bool] controls whether triggers are automatically expanded when they are typed in insert mode. true by default.

Snippets can be selected manually with the commands snippets and snippets-menu.

At any moment, the snippets-info command can be used to show the available snippets and their respective triggers.

Triggers

Snippets can be executed when a certain string is written directly in the buffer with the help of triggers. To each snippet is associated a regex which we call a trigger.

Triggers can be automatically expanded by setting snippets_auto_expand to true, or they can be expanded manually by using the snippets-expand-trigger command. By default, this command tries to expand the current selection if it is a trigger, but you can also pass it an argument to select a different part of the buffer.

The option snippets_triggers_regex can be used to help select triggers. It's a simple alternation of all triggers as a single regex.

For example, this call will try to select a trigger on the current line and expand it. If it fails, the selection stays unmodified.

snippets-expand-trigger %{
    reg / "%opt{snippets_triggers_regex}"
    # select to the beginning of the line, and then subselect for one of the triggers
    exec 'hGhs<ret>'
}

If a snippet does not have a trigger (i.e. it's empty), you won't be able to use it via expansion, but the basic commands snippets and snippets-menu can still be used.

Defining your own snippets

Snippet commands are just regular kakoune command, so you can do just about anything in them.

Ideally, your snippet command should work in both Insert and Normal mode, so that it can be used via auto-expansion and manual snippet call (be careful about this kakoune issue).

snippets-insert

snippets-insert is a builtin command of the script that can be used to insert text with proper indentation and optionally move/create cursors. It accepts one argument which is the snippet to be inserted at the cursor(s).

Tabs should be used for indentation when defining snippets, they will be automatically converted to the appropriate indentation level (depending on indentwidth)

The snippet supports custom syntax to define cursor placeholders, which define the resulting selections after expansion. A cursor placeholder is defined with ${} (empty selection) or ${text} (default selection text). To use a literal $ inside a snippet or a literal } inside a placeholder, double it up ($$ and }}).

When a snippet is inserted with snippets-insert, all placeholders are selected. If there are none, the entire snippet is selected.

Changelog

  • Removed snippets-directory.kak and numbered placeholder support from snippets-insert (see disclaimer at the top)
  • ${indent} has been removed in favor of changing leading tabs to the preferred indentation
  • any value can now be used as a trigger. They're regexes, so escape them accordingly
  • implicit \b are not inserted anymore before and after triggers. The internal option %opt{snippets_expand_triggers} has been renamed to %opt{snippets_triggers_regex}
  • snippets_triggers and snippets have been merged into a single option
  • triggers can now be manually expanded by calling the snippets-expand-trigger command on a valid trigger
  • snippets_auto_expand is now a boolean that controls whether auto-expansion of triggers is enabled
  • snippets_auto_expand was renamed to snippets_triggers

FAQ

What's the performance impact of the extension?

If you use the auto-expansion feature, a runtime hook is run on each Insert mode key press. It only uses a shell scope in case of a match, and stops early otherwise.
If you don't use it, there is no runtime cost (except when executing a snippet of course).

What's with escaping, what kind of characters can I use and not use?

You should be able to use anything. Triggers are currently restricted to at most 10 characters (at least for auto-expansion), but the number is arbitrary and we could raise it.

My snippets are expanding too greedily. If I type 'before', I don't want my 'for' snippet to be expanded.

You should use a stricter trigger for the snippet. For example, \bfor will only expand if for starts at a word boundary. Similarly, you can use ^ to match the start of a line.

How did you do the demo?

It's done using kitty's remote control features, a 'manuscript' and a script to bridge the two. I'll upload them at some point.

Tests

The test.kak_ file contains tests for the plugin. To execute these tests, simply run kak -n -e 'source test.kak_ ; quit': if the kakoune instance stays open, the tests have somehow failed and the current state can be inspected.

Similar extensions

https://github.com/alexherbo2/snippets.kak
https://github.com/shachaf/kak/blob/master/scripts/snippet.kak

License

Unlicense

kakoune-snippets's People

Contributors

andreyorst avatar charlesgueunet avatar codesoap avatar occivink avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

kakoune-snippets's Issues

Doc is not clear on how to define snippets other than in snippets-add-snippet

Hi,
I'm new to snippets (and to Kakoune) and loving it. Until now I've been using the snippets-directory extension, but I'd rather just have all my snippets for a given language written in one file (whose name could be interpreted as a regex like when using snippets-directory).

The thing is I simply can't figure out how to add a new snippet other than using the add-snippets command (which creates a file) or manually adding a file myself. Based on syntax that I saw written in other issues, I added this to my kakrc:
hook global WinSetOption filetype=latex %{
set -add buffer snippets "hello" "\h" %{snippets-insert %{\hello{$1} $0}}
}

But this only expands when I write "\h " and when it does it doesn't remove the "\h", the result is "\h\hello{}". Yet most (not all) of the snippets I added as a file using a directory work as expected (it's really nice!).

Is there something I'm not getting here? Sorry if this is a stupid question. Ideally I'd rather have all my snippets in one place. Thanks in advance.

Indentation is mixed by spaces and tabs

I set aligntab option to false in my configuration file because I don't want tabs in alignment, but it seems that this option affects how indentation is handled in this plugin.

I've expanded some snippets, and then changed the option to true
image
Notice light vertical bars representing the tabs.

Dependency section

Maybe it is a good idea to include a dependency section.
For a starter it seems to depend on perl.

[Feature Request] Discard default text if nothing is changed

The use case for this would be as follows:

\usepackage[possibly something]{definitely something}

could there be an option so that the default text of [] would be deleted if you just jumped to the next snippet?

Hope this makes sense and thanks for the great plugin!

[Feature Request] Allow loading snippets from separate files

This will allow to create snippet packs for users who don't want to define their own snippets, and will hugely help organize snippets for different languages.

The stcucture should look like that:

snippets # multiple files per fyletype directory
    Cpp
        for.snip
        if.snip
    Java
        for.snip
        if.snip

snippets single file for single filetype
    cpp.snippets
    java.snippets

Of course those fies can be an arbitrary kakoune scripts, but it would be more common to define a filetype for snippet files, add a syntax highlighting.

Snippets can be one snippet per file located in fyletype folder, like in yasnippet, or one file per filetype with all snippets for current language as shown in the example above.

  • The first method involves getting a trigger and finding a file with the name same as trigger. That's yasnippet and simplesnippets.vim approach
  • The second method involves parsing a snippet file, to find a trigger inside it, and extract snippet from it. That's Ultisnips and Vscode approach

:snippets-info does not work for rust filetype

I've accompanion kakoune-snippet-collection plugin installed and have following setting in my setup:

set-option -add global snippets_directories "%opt{plug_install_dir}/kakoune-snippet-collection/snippets"

However invoking :snippets-info command in rust files shows nothing, I mean there is no pop up at all. This is strange as it works in go files for example. I tested in macos and arch linux and it is same behaviour.

Thrigger with same ending as another trigger will call wrong snippet

defining this two snippets, will result in availability of only one of them:

set-option -add window snippets 'if {}' 'if' %{
    snippets-insert 'if ($1) {
                     ${indent}$0
                     }'
}

set-option -add window snippets 'if {} else {}' 'elif' %{
    snippets-insert 'if ($1) {
                     ${indent}$2
                     } else {
                     ${indent}$0
                     }'
}

If I type elif and hit my expand key, if snippet will be expanded instead of elif.

Replace first placeholder with selection

A command like snippets-insert-replace-first-placeholder which would trigger a prompt, to which you would write the name of your snippets, which preferably only has one placeholder. Then, your current main selection would be the default value for the first placeholder.

A nice usecase would be \textbf{} and many other stuff in LaTeX.

[Feature Request] Transformations

Documentation of transformations for LSP style snippets may be needed to support lsp snippets.

Basically transformations allows modifying the placeholder contents, before it is inserted with sed-like commands written inside the placeholder.

You can also check transformations in UltiSnips, which can actually execute shell, python and vimscript: UltiSnips#Interpolation

There's also yasnippet for Emacs, that allows to do some cool real time transformations. You can check the docs here

Kakoune hangs when trying to add snippets

simply executing of :set-option -add window snippets 'trigger' 'snippet' results in endless waiting for shell to finish.

*debug* buffer shows insanely huge log:

...
sh: line 5: shift: 3: shift count out of range
sh: line 5: shift: 3: shift count out of range
sh: line 5: shift: 3: shift count out of range
sh: line 5: shift: 3: shift count out of range
sh: line 5: shift: 3: shift count out of range
sh: line 5: shift: 3: shift count out of range
sh: line 5: shift: 3: shift count out of range
sh: line 5: shift: 3: shift count out of range
sh: line 5: shift: 3: shift count out of range
sh: line 5: shift: 3: shift count out of range
>>>
error running hook WinSetOption(snippets='trigger' 'snippet')/: 2:6: 'set' regex parse error: regex parsed to more than 32767 ast nodes at '\A�(snippet|snippet|snippet|snippet|snippet|snippet|snippet|snippet|snippet|snippet|snippet|snipp...

snippets_auto_expand appears to do nothing

Weirdly enough, when I first got this plugin it would automatically expand snippets by default despite saying that wasn't the default behavior.

More annoyingly though, is that it has suddenly stopped doing that for some reason I can't figure out. And I can't seem to get that behavior back:

set global snippets_auto_expand true

That line doesn't do anything, I've tried it with different snippets in different languages but it doesn't auto-expand.
I've also confirmed that using the :snippets-expand-trigger and such commands manually does work, but that's hardly an efficient solution.

Is this a bug, or (more likely) am I just doing something wrong? I'm very new to kakoune, so I wouldn't be surprised if my syntax is incorrect. Thanks in advance for any help!

[Feature Request] Display triggers in completion menu

It would be cool to see available triggers as you type, much like we are able to see completions of language facilities.

It could display a trigger, and info inside information field like so:
image
but instead of __fortify_function there will be some trigger, say for, instead of Interface there will be Snip or Snippet, and instead __fortify_function will be the snippet description for loop

I also wonder how it will play when https://github.com/mawww/kakoune/tree/completions-commands arrive. Could it be possible to expand snippets on completion, or if special key is pressed after the completion, and so on.

[Feature request] Expose jumping abilities

Jumping can accept the count variable.
It also could be handy to be able jump backward in case you edited some placeholder wrong.
Ability to skip whole snippet and jump directly to the last placeholder also comes in handy when snippet is fine by default.

[Feature Request] Standard snippet syntax

The most common snippet syntax is adopted by many projects, like language servers, different editors like Visual Studio Code, Sublime Text, Emacs (via Yasnippet), Vim (via Ultisnips and SnipMate), TextMate, and possibly others.

The syntax for snippets can be found at LSP documentation: snippet syntax

Supporting universal snippets would allow to reuse snippet definitions from other editors wit less amout of reworking those.

[Feature Request] Expand snippet on special keypress

It would be handy to have an option to expand snippets when some user-definde key is pressed. Automatic expansion is good feature, but not always wanted.
I like to expand snippets with Tab, and jump betwen placeholders with Tab too. This involves some problems when you actually want to insert tab character. When I've designed SimpleSnippets.vim, I've implemented a function, that checked if typed text is a trigger, and if it is it inserted a snippet, otherwise it acted as tab key was pressed. That allowed me to use tab to completions and snippets.

The plugin doesn't work in kak headless session mode

If I run kak in a headless session mode like kak -d -s mysession, then connect to that session with kak -c mysession, none of the plugin related commands work, same with snippet expansion in insert mode - it doesn't work.

Integrate with completion menu

By now I have disabled auto expansion and I've mapped : snippets-menu<ret>/ to a key to have a fast way to open up a snippet search-and-insert menu.
Could it be possible to integrate/merge the snippets menu into kakoune autocomplete engine?
For example, when I type fo the autocomplete menu could show both the for word/ and the for snippet (that expands when selected with c-n).
Haven't yet looked into how autocomplete is implemented, implementing this would be really cool.

LSP completion snippets

I use bingo lsp server with kak-lsp. Completion has some snippet like placeholder. I installed this plugin with hope, that I'll be able to jump to that placeholders, but nothing happens out of the box.
Screenshot-2019-02-15-at-16-22-02.png

Is it possible to jump to placeholders in such completion snippets? If yes how do I config?

Snippet load error

during testing #23 Ive encountered problem with loading jdj'\;;l - -=[]\,.kdj. I don't think that anyone would use such thing, but obviously there shouldn't be any error since all characters are valid.

error running hook WinSetOption(snippets='-=[]\,.kdj' 'jdj''\;;l' 'snippets-insert ''vaiv'' ')/: 2:6: 'set' regex parse error: unknown atom escape ';' at '(jdj'\;<<<HERE>>>;l)'

Change insertion to start at first word boundary

I think this should go in snippets-expand-trigger but I'm not exactly sure as I'm still trying to make sense of the code.

I set a few of my snippets to trigger at the start of a line with respect to indentation by adding ^(\s*) to the start of the trigger.
for example (\s*)do triggers:

do

and

try:
    do

but not

todo

or

to do

that way the snippet would work so long as the trigger is the first thing on the line, other than white space.

currently the function inserts the triggered snippet starting at the line (which makes sense because technically the whitespace was part of the trigger). it would make sense though to change this so that snippets could work with indentation.

[Feature request] Infinite expansion

Hi,

Even though it seems the development of this project has been 'abandoned' I was just wondering if a particular use-case could be dealt with by this kind of framework hypothetically -- for further reference, I suppose. I'm not aware that this is possible with other snippet managers but I very well could have missed it.

In LaTeX, bulleted and numbered lists are indicated by itemize or enumerate environments. In these, the bullets or numbers are denoted by \item.
One of my snippets expands to

\begin{itemize}
  \item |
\end{itemize}

(the pipe is where my cursor ends up).

What I imagined was that pressing <Tab> could trigger a new \item statement to appear:

\begin{itemize}
  \item blah blah blah...
  \item |
\end{itemize}

and so on each time <Tab> is pressed in this environment.

I hope I was clear enough. Would this be feasible hypothetically or would we need something more powerful?
Thanks.

Expansions inside snippets

Hi, I'm trying to define some global scope snippets, I've been able to do so with a '(.*)' directory, but I also want to be able to declare
expansions in snippet and run it in the context I'm in, for example I often use this convention when commenting code to have
context about when that happened, and I would like to have it for any file type, and being able to eval those expressions easily,
%opt{comment_line} NOTE %sh{date}, I clearly could do this with a user define command and mapping, but the idea to use snippets
for other purposes more than code itself would be an interesting idea, and the framework this plugin provides could be used to provide such feature, I would like to know what you think about.

thanks for you work!

Snippet always expand to the first entry

Using kakoune master, the expand of a snippet always trigger my first snippet.

more details

I have the following configuration for kakoune snippet:

  set-option -add global snippets_directories "%opt{plug_install_dir}/kakoune-snippet-collection/snippets"
  set-option global snippets_auto_expand true

  map global insert '<c-s>' '<a-;>: snippets-expand-trigger<ret><esc>'
  map global insert '<c-n>' '<a-;>: snippets-select-next-placeholders<ret><esc>'
  map global normal '<c-n>' ': snippets-select-next-placeholders<ret>'

I work only on CPP. Whenever a snippet is triggered, the result is:

#include <iostream>

even if I typed for, main, ...

I also tried to call the snippet-expand-selection manually with the same result.

Best,
Charles

Plugin should do nothing if Perl not installed

Currently if perl isn't installed, plugin works only in half way: snippet is inserted, but indentation and cursors are not. This may look misguiding for new users, because they may miss that Perl is required. It would be better if plugin tested command -v perl and throwed an error and info message about it's requirements.

Using |} in snippet trigger seems to break loading

Another snippet for Rust.

filename: |} - Closure, anonymous function (block)

${1:move }|${2:what}| {
        ${0:/* body */}
}

Trying to load this snippet produces this error message:

error running hook WinSetOption(snippets='Closure, anonymous function (block)' '|}' 'snippets-insert ''${1:move }|${2:what}| {
	${0:/* body */}
}'' ')/: 2:6: 'set' regex parse error: unexpected '}' at '(|<<<HERE>>>})'

Feature-set of modern snippet manager

There's only two commits at this point, but it's a great plugin already, and since I've already created a snippet manager for another editor, I'd like to provide a list of features that would be super great to have:

  • Embedded functionality to jump between placeholders
    with Tab and S-Tab, or other user defined mappings.
    • Enter could be mapped if expansion keys are match snippet
      and completion popup is opened.
  • named placeholders,
    e.g. {{TEXT:SELECTION}}, so selection could contain default text on expand.
  • Placeholder order,
    e.g. {{1:TEXT:SELECTION}, so we could jump in needed order, and skip whole snippet if needed.
  • Standard snippet syntax, e.g.
    ${1:TEXT}, $2, so other snippets from other managers could be ported and used. This also will make possible to use LSP snippets. Here's a LSP snippet standard, but it's pretty common for other snippet managers too. I've implemented it in my snippet plugin for Vim.
  • Mirroring,
    e.g. ${1:TEXT} and $1 will share same TEXT on expansion.
  • Distinguish mirrored placeholders from normal placeholders,
    so jumping will select needed amount of selections to modify.
  • Zero placeholder ${0:TEXT} or $0 as last placeholder
    and jumpout of snippet boundares would be cool.
  • Visual placeholder ${VISUAL}
    that can yank text and place it to the snippet body.
  • Placeholders with selectable choice variants,
    e.g. ${1|hello,world|}, so on jumping popup menu will allow to select a candidate. I'm not sure if it is possible with Kakoune though.
  • Transformations................ This is tough.

I'll dig into your implementation and see if I can help with implementing those features. I also might extend this list if I remember something that I've didn't mentioned.

[Feature Request] Placeholders with selectable choice variants

The syntax is ${1|first,second,third|}. Upon jump on such placeholder first option is selected an a popup menu is shown with other variants. If completion menu could be utilized for this it will be the best solution, since we can just dicard it without confirmation, and all other snippet managers use it.

Whitespace at beginning of line

I have the following snippets

    set -add buffer snippets \
    "comment" "/*" %{snippets-insert %{/*
 * $1
 */}}

I would like to have the whilespace before the * characters to persist into the snippets, currently it seems to be removed

Show snippet expansion token, instead of snippet name

At the moment commands snippets and snippets-menu list snippet names.
Usually when I type, I need to know what expansion token is, not what snippet name is. It is not very convenient, because there is no way to see expansion tokens available, without context switching.
In my opinion at least snippets-menu should list snippet expansion tokens.

`(` in snippet file name cause error

If I add this snippet for kak filetype:

touch "^hello - (descr)"
echo snippet > \^hello\ -\ \(descr\) 
kak test.kak

In *debug* I see:

shell stderr: <<<
sh: 1: eval: Syntax error: "(" unexpected

Snippets itself seem to work fine. This is on auto-discard branch.

Add configuration example

The docs mention:

snippets [str-list] is a list of {name, trigger, command} tuples. The name is the identifier of the snippet, the trigger is a short string that identifies the snippet, and the command is what gets eval'd when the snippet is activated. In practice it's just a flat list that looks like snip1-name snip1-trigger snip1-command snip2-name snip2-trigger snip2-command...

While this is descriptive, I'm still having a bit of trouble figuring out how I'd configure this plugin if I have, say, a directory of snippets somewhere. A real world configuration example for the snippets option would be appreciated!

Can't expand rust closure snippet

I've ported my snippet collection to work with your plugin, and now I'm testing it.

I can't expand || snippet, which is defined like so:
filename: || - Closure, anonymous function (inline)

${1:move} |${2:entry}| { ${0:/* body */} }

Doc is not clear on how to expand snippet on keypress

Hello,
I think most of people expect from snippet plug to have to following behavior:
type for then press a key so the for expand to

for $X in $COL:
    $BODY

and then press another key ( usually tab) to move from $X to $COL to $BODY.

I think this the default way of using snippet, but it's really not clear how to do that in the doc. I feel this should be inside the ##Usage paragraph

Snippet trigger max length

I have been trying this plugin for a while and it's great but I'm having a problem with trigger lengths. Some commits before, I could use some slightly longer triggers but now they are failing. After checking the source, the reason is that you are calling "h6h", limiting the trigger length to 6.

Is there a good reason why it's set to that number? Is it expected for the triggers to be always short?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.