Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Snippets plugin: initial version #1113

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open

Conversation

igordsm
Copy link
Sponsor Contributor

@igordsm igordsm commented Oct 6, 2021

Fix #36

I'm proposing an initial version for a Snippets plugin. Basic editing works for placeholders and it's already useful on its own. The following features are implemented.

  • language specific snippets
  • placeholder for tabstops inside the snippet
  • placeholder for cursor after editing all placeholders
  • blocks interactive completion during placeholder editing
  • cancel placeholder editing after 500ms without pressing any key

It does not have (yet) support for default values or variables. I'm opening this PR to get some input on the following decisions:

  • Should we use a format shared by other editors? Sublime and TextMate are very popular and maybe adding support for importing their files directly would be interesting. VScode also has a specific JSON format for snippets and support Sublime and TextMate "snippet language".
  • Should we ship any snippets? Should we update them only when Code releases?
  • Where are snippets stored? I'm currently using XDG_USER_DATA_DIR (or something like that)/code/snippets/snippets.json, but if we ship snippets then this will change.
  • Do we want to support user snippets if we opt for shipping snippets?

A basic version with no snippets shipped and only user snippets supported already works. The snippets.json shows how to create snippets. The only problem with the current code is that it does not maintain indentation, so snippets for code might produce invalid code for some languages. There is relevent a discussion in #1098 that proposes moving part of the indentation plugins to the main code.

@jeremypw
Copy link
Collaborator

jeremypw commented Oct 6, 2021

Just a few preliminary code style comments. I'll have a more detailed look later. Probably best not to try and pack too much functionality into one PR. Choosing and inserting a few builtin (Vala) snippets is probably enough for a first step.

@igordsm
Copy link
Sponsor Contributor Author

igordsm commented Oct 6, 2021

@jeremypw Thank you for the quick and extensive review. I'll work on these points as soon as I can.

@igordsm igordsm marked this pull request as ready for review October 18, 2021 23:12
@igordsm igordsm changed the title [Draft] Snippets plugin: initial version Snippets plugin: initial version Oct 18, 2021
@igordsm
Copy link
Sponsor Contributor Author

igordsm commented Oct 18, 2021

I feel like this is ready for review now. A set of vala snippets is shipped with the plugin. You can see it in action below

snippets

Some noteworthy changes:

  1. moved some functions from the preserve indent plugin to Scratch.Utils. They are probably useful in other plugins/features as well
  2. the timeout to cancel an edition is 1 second
  3. snippets.json is installed to PLUGINDIR/snippets/snippets.json

@igordsm
Copy link
Sponsor Contributor Author

igordsm commented Oct 28, 2021

Merged master. I'm available to iterate on this, just let me know. We can also talk on slack about it if sync communication is better.

Copy link
Collaborator

@jeremypw jeremypw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible for the candidate options to include the Alt as well as the number which is required for the hotkey to work? Or do you think the user would be expected to know that?

This plugin does not work if the Word Completion plugin is active. Is that fixable?

@jeremypw
Copy link
Collaborator

jeremypw commented Nov 3, 2021

This is shaping up as a useful addition though -thanks for working on it!

@igordsm
Copy link
Sponsor Contributor Author

igordsm commented Nov 7, 2021

@jeremypw From my poking around it seems like Word Completion does not play well with other completion providers. It seems to assume that it's the only completion provider and invalidates the context when it doesn't have proposals. I can send another PR that "fixes" this before this one is accepted. What do you think about that?

I used standard GtkSourceView widgets. I believe it's expected that the user understands how to use it. Honestly, I was always selecting with the arrows and it took me a while to realize that I could use Alt+2 for the second option. Same for Alt+D for details.

I added details to each snippet, so at least it's easier to know what they will do.

image

@jeremypw
Copy link
Collaborator

@igordsm Using the builtin SourceCompletion UI is fine for now although it looks rather ugly (to me). More of a problem is how different completion plugins are going to work together. There are potentially three: this one, the existing word-completion plugin and the proposed GVLS plugin. Is there a way of making all these work together or are we going to have to make them mutually exclusive?

@igordsm
Copy link
Sponsor Contributor Author

igordsm commented Nov 10, 2021 via email

@esodan
Copy link

esodan commented Nov 21, 2021

I'm working on making the word completion plugin play nice with others. It assumed that it was the only one and did lots of strange things. As soon as I can test it together with snippets I'll send a draft PR. I'm convinced that completions providers can work together without problems.

On Wed, Nov 10, 2021 at 5:31 AM Jeremy Wootten @.***> wrote: @igordsm https://github.com/igordsm Using the builtin SourceCompletion UI is fine for now although it looks rather ugly (to me). More of a problem is how different completion plugins are going to work together. There are potentially three: this one, the existing word-completion plugin and the proposed GVLS plugin. Is there a way of making all these work together or are we going to have to make them mutually exclusive? — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub <#1113 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABWCBR5DELZ43B2QYDB5JLULJCWVANCNFSM5FOW33AA . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.
-- Igor Montagner http://igormontagner.blogspot.com/

You should consider that GVls plugin and potentially others use async completion fill, that means you should consider to add proposals and pass false to add_proprosals() when your plugin is still in the works and true when it finish so make the others create its own proposals. Look at GVls's code.

I propose you to add you snippets to GVls so it can provide context snippets as completions using Microsoft LSP specification for snippets. This will help to avoid the problems above.

Also is possible to add a word index in GVls for an specific buffer and provide completion proposals for words, that may is useful and will fix the issue with current plugin requiring to deactivate it.

@jeremypw
Copy link
Collaborator

I can't help thinking that we should not get too tied into GVLs at this stage - is it not possible to write a more generalized LSP client plugin that could use any LSP compliant server and keep the server code more at arm's length? I need for one need to find time to do a lot more work on understanding language servers in general and GVLs in particular.

I take the point that we need to consider how to make synchronous and asynchronous completion processes work together at some point. Not sure it should block release of this plugin as we do not have a working VLS plugin implementation yet.

@esodan
Copy link

esodan commented Nov 26, 2021

I can't help thinking that we should not get too tied into GVLs at this stage - is it not possible to write a more generalized LSP client plugin that could use any LSP compliant server and keep the server code more at arm's length? I need for one need to find time to do a lot more work on understanding language servers in general and GVLs in particular.

GVls provides a generic LSP client and a Server Manager to easy connect to any out there.

May you want to create a Vala snipped library so I can integrate it into GVls so that will be transparent for you. Your library could be used to write snippets plugins to any Vala editors or any thing out there.

I can help you to create your library if you want, so we can share work and help you to avoid understand how GVls or any other LSP client/server works.

I take the point that we need to consider how to make synchronous and asynchronous completion processes work together at some point. Not sure it should block release of this plugin as we do not have a working VLS plugin implementation yet.

As I've explained before, you should consider add_proprosals() to consider that async work on in the middle you (or both) work to write a snippets library for Vala, so any like GVls can add proposals and avoid conflicts with multiple completion providers.

GVls plugin in working, more integration to code will help to provide generic LSP client, that that is another history.

@taozuhong
Copy link

taozuhong commented Aug 16, 2023

    public class CodeUnit : Object {
        public struct TextUnit {
            int64 start;
            int64 end;
        }

        private ArrayList<TextUnit?> m_text_units;

        public string trigger { get ;set; }
        public string database { get; set; default = "SQL"; }
        public string category { get ;set; default = ""; }
        public string description { get ;set; default = ""; }
        public string text { get; set; default = ""; }
        public ArrayList<TextUnit?> placeholders { get { return m_text_units; }}

        construct {
            m_text_units = new ArrayList<TextUnit?>();
        }
    }

I'm implementing the same thing with GtkSourceView5, I use the class above to represent the snippet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Snippets Plugin
5 participants