12

Is it possible for a snippet to insert a dynamically computed completion or snippet in Visual Studio Code?

I would like a snippet for inserting date and time strings of various formats. For example if you type date, the current date in ISO format would automatically be expanded.

example of dynamic snippet expansion with dates

There is a facility in Sublime Text to do this in the python API via the on_query_completions method in the EventListener class. There the implementation would be very simple:

def on_query_completions(self, view, prefix, locations):
  if prefix == 'date':
    val = datetime.now().strftime('%Y-%m-%d')
  return [(prefix, prefix, val)] if val else []

I have read the documentation on User Defined Snippets, but it appears that one can only insert pre-defined text with tab-stops and variables that the user fills in.

If this isn't possible with the functionality exposed by the snippet API, would I be able to implement something similar with via a lower-level plugin/extension API?

I do realize that there is an existing extension called Insert Date and Time but this works via the command pallet instead of a dynamic expansion.

dreftymac
  • 31,404
  • 26
  • 119
  • 182
Chris Scott
  • 1,721
  • 14
  • 27
  • You can use the [Command Variable](https://marketplace.visualstudio.com/items?itemName=rioj7.command-variable#datetime) extension and define keyboard shortcuts – rioV8 Aug 09 '20 at 11:58

2 Answers2

9

It's definitely not possible to execute a script or something similar within a snippet.

You can write an extension for Visual Studio Code instead. The extension must implement a CompletionItemProvider.

Its provideCompletionItems method would return a list of CompletionItems. Their filterText properties would be set to the texts displayed in the suggestion box (for example "date" or "time") and their insertText properties would be set to the dynamically computed values.

Finally you would need to register the completion provider using registerCompletionItemProvider.

You should absolutely take a look on how to create an extension before you start: https://code.visualstudio.com/docs/extensions/example-hello-world

Wosi
  • 41,986
  • 17
  • 75
  • 82
  • Thanks, that pointed me in the right direction. Using `CompletionItem`s to implement isn't quite a simple as ST for this use case, but it does afford more flexibility. – Chris Scott Sep 12 '16 at 17:35
  • 2
    @chris-scott, I was searching for how to do the same thing (and for the same reason - timestamps in different formats). Since it sounds like you have it working, care to share your extension or put it on the VS Code Marketplace? :) – Dullroar Sep 16 '16 at 15:44
  • 1
    @Dullroar, yes I am planning to. I haven't tested it outside of dev mode which is why I haven't published it yet, but I will upload to github so that you can take a look. – Chris Scott Sep 19 '16 at 13:23
  • Looking forward to it. – Dullroar Sep 20 '16 at 22:39
  • is this still the case or any update on this one ? Googled but didn't found anything :( – sreenivas Sep 05 '17 at 04:51
  • You can execute scripts in snippets with [HyperSnips](https://marketplace.visualstudio.com/items?itemName=draivin.hsnips) and the `insertText` can be a [dynamic constructed Snippet](https://code.visualstudio.com/api/references/vscode-api#CompletionItem.insertText) – rioV8 Aug 09 '20 at 10:12
6

Although, it's possible to achieve simple date-time stuff without extensions:

"⌚ Date Time SNIPPET": {
    "prefix": "datetime",
    "body": [
        "${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE}T${CURRENT_HOUR}:${CURRENT_MINUTE}:${CURRENT_SECOND}",
    ]
}

The question is about dynamic snippets. And here's an example of using CompletionItemProvider:

const datetimeProvider = vscode.languages.registerCompletionItemProvider(
    {
        scheme: 'file',
        // language: 'typescript',
    },
    {
        provideCompletionItems(document: vscode.TextDocument, position: vscode.Position) {
            const completionItem = new vscode.CompletionItem('datetime ⌚', vscode.CompletionItemKind.Snippet);
            completionItem.insertText = new Date(Date.now() - new Date().getTimezoneOffset() * 60000).toISOString().split('.')[0];
            return [completionItem];
        }
    },
    // ''// trigger character
);
Alex
  • 59,571
  • 22
  • 137
  • 126