Visual Studio Code Snippets - окончателното VS Code Snippet Guide за начинаещи

Фрагментите могат да добавят нотка на магия към вашия редактор. Това е като заклинание. Кажете кратка фраза (въведете префикс), размахайте пръчката си (натиснете Enterили Tab) и престо! Пред вас се разкрива прекрасно събитие. ✨

Повечето редактори на кодове поддържат фрагменти от кутията. Редакторът на кодове, който ще използвам за представяне на фрагменти, е Visual Studio Code (VS Code), най-популярният редактор за деня.

Освен това има някои приложения за разширяване на текст, които ви позволяват да използвате фрагменти в световен мащаб (във всички приложения). Накратко ще разгледам как можете да използвате тези приложения, за да извлечете още повече от фрагментите.

Нека да се потопим във всички фрагменти. ?

Определение

Фрагментът е шаблон, който може да се вмъкне в документ. Той се вмъква чрез команда или чрез някакъв задействащ текст.

С фрагменти можете да създадете шаблонния файл и да вмъкнете често използвани блокове текст. Общата идея е да ви спестим да въвеждате едни и същи неща напълно отново и отново и отново. ?

Защо трябва да използвате фрагменти?

Няма да ви шокирам с това твърдение: интернет е дом на много противоречиви мнения! Фрагментите не убягват на тази позорност, но не мисля, че това е тема, която кара кръвното налягане на хората да скочи!

За баланс тук ще представя напречен разрез на тези мнения.

Не е нужно да избирате лагер и да бъдете "за" или "против" фрагменти. Предлагам ви да ги приемете до степен, която ви служи най-добре.

Yay Camp?

  • Фрагментите могат да повишат вашата производителност, спестявайки ви натискания на клавиши и намалявайки грешките при въвеждане.
  • Snippets ми оставя повече психически процесор и удоволствие, които да похарча за писането на кода, за който се грижа и върху който искам да се съсредоточа.
  • Фрагментите могат да ви помогнат да запомните да включите нещо важно!
  • Интегрирането на фрагменти във вашия работен процес имплицитно ви насърчава да използвате мишката по-рядко. Добре написаните фрагменти предлагат логичен път, през който можете да преминете, като спрете да редактирате по пътя, за да завършите шаблона точно така, както искате, и когато сте готови, пристигате от другата страна, готови да напишете следващия си ред

Най-лагер?

  • Въздържам се да ги използвам, най-вече защото не обичам да разчитам на даден инструмент.
  • Никога не използвам фрагменти. Предпочитам да инвестирам време в избягване на повторения, вместо да го улеснявам.
  • Установих, че в един момент забравих как да напиша кода, без да използвам фрагмента. За тривиални неща, които разбирам, е добре, но не искам да забравя някои други неща!
  • Повечето, ако не всички, фрагменти, които съм виждал онлайн, за кода, който търся, имат грешки в тях. Не веднъж съм успял да намеря числов алгоритъм, в който да няма грешки с плаваща запетая. Не мога да си представя, че има някакъв ресурс от напълно изчистени кодови фрагменти.

Кога трябва да използвате фрагменти?

Доналд Кнут, един от големите магьосници по компютърни науки, каза, че „преждевременната оптимизация [на кода] е коренът на цялото зло“.

Мисля, че това е от значение и за фрагменти. Фрагментите са оптимизация на производството на код. Ако не знаете много добре език или рамка, внедряването на множество фрагменти за този език или рамка вероятно ще бъде преждевременно движение.

Ако ви е удобно, опитайте малко!

За какво използвам фрагменти

Лично аз използвам фрагменти често, но разумно. Използвам набор от фрагменти за Markdown и повечето езици, с които работя.

Не съм използвал фрагменти много за рамки. Започнах да използвам някои фрагменти за Vue наскоро, но използвам само шаблонния фрагмент. Вероятно ще приема повече от тях, след като моят Vue IQ се повиши.

Не съм използвал фрагменти за алгоритми.

Видове фрагменти

Фрагментите могат да бъдат класифицирани според обхвата на интерактивност между фрагмента и редактора.

Статични фрагменти

Можете да го възприемате като копиране и поставяне на някакъв изходен текст като една команда.

Динамични фрагменти

Динамичен фрагмент може да бъде персонализиран, за да осигури подобно на съветника изживяване за завършване на фрагмент.

Тя може да включва:

  • Tab Stops : Можете да номерирате спирки, които могат да бъдат подредени по ред,
  • Огледални раздели спира : Има моменти, когато трябва да предоставите една и съща стойност на няколко места във вмъкнатия текст. Можете да отразявате табулатор, за да постигнете това, и всяко редактиране ще бъде отразено незабавно в свързаните табулатори.
  • Заместители : Това е спирка с раздели със стойност по подразбиране, която може да бъде заменена на фокус.
  • Избор : На таб спирка ви се представя падащ списък със стойности, от които можете да избирате.
  • Променливи : Въведени стойности от средата, като: избраният текст в редактора, системни дати или съдържание от клипборда.

Ето пример за фрагмент за маркиране, който добавя списък със задачи с 2 задачи. Той използва спирки на табулатори , заместители и избор за проверка на задача.

задача

Макро фрагменти

Най-горното ниво на магьосничеството е да има способността да трансформира входа. Трансформациите ви позволяват да промените стойността на променлива, преди да бъдат вмъкнати, или да промените заместител, след като сте направили редакция.

Например, може да искате да напишете името на класа с главни букви, след като бъде въведено.

Всичко, което можете да си помислите да правите с регулярно изражение, обикновено е възможно. Някои редактори предлагат по-разширени възможности за скриптове.

Фрагменти в Visual Studio Code

In VS Code, snippets appear in IntelliSense (Ctrl+Space gives you a suggestion list), they are mixed in with other suggestions.

You can also access them in a dedicated snippet picker by using the 'Insert Snippet' command. This combines all user, extension, and built-in snippets for that language into a single list.

insert-snippet-list

Emmet is integrated into VS Code and has it's own CSS-selector inspired syntax for inserting HTML and CSS snippets.

Emmet is it's own thing really, but the mechanics are the same. You can learn about Emmet with the Emmet in Visual Studio Code guide.

Related User Settings

Snippets will appear as quick suggestions if the setting editor.quickSuggestions is set to true for the language you are working in. Quick suggestions are enabled by default for most languages except markdown.

бързи предложения-js

Snippets support tab-completion. You can type a snippet prefix (the trigger text), and press Tab to insert a snippet. You can enable it with the setting editor.tabCompletion.

The values are:

  • on: Tab completion is enabled for all sources.
  • off: Disable tab completions. This is the default value.
  • onlySnippets: Tab completion only for snippets.
"editor.tabCompletion": "onlySnippets", 

If you would like to control how snippets suggestions are shown, you can edit the setting editor.snippetSuggestions.

The values are:

  • top: Show snippet suggestions on top of other suggestions. I use this value.
  • bottom: Show snippet suggestions below other suggestions.
  • inline: Show snippets suggestions with other suggestions. This is the default value.
  • none: Do not show snippet suggestions.
"editor.snippetSuggestions": "top", 

These are the most important settings for snippets, but there are a few more. You can check out this list of the default settings to explore more, or do a search in the Settings UI.

Are there built-in snippets?

Yes!

They aren't documented in the VS Code docs, though. And inside VS Code, there is no central point to browse them. So, you may not know what they are.

So, how can you find out what languages have built-in snippets?

Long story short, I was frustrated by this scenario, so I wrote an extension called Snippets Ranger to give a nice UI to explore snippets easily. Think of it as a Marauder's Map for snippets!

snippets-ranger

But I want to find the snippets for myself?

You can, it just requires a bit more effort.

As I mentioned earlier, the 'Insert Snippet' command will show you all snippets for the language of the active document.

Remember though, this is an aggregate of all of the user, extension, and built-in snippets. So, if you want to find out if a particular language has built-in snippets, you need to open a file for that language, and run the command to see that list.

If you have an snippets extension installed for that language that makes it too hard to identify which is which, you could disable it to ensure that only the built-in snippets are showing. ?

If you want to track down the source file yourself, the built-in snippets live inside each individual language extension directory. The file is located at «app root»\resources\app\extensions\«language»\snippets\«language».code-snippets on Windows. The location is similar for Mac and Linux.

Snippets Extensions

The Visual Studio Marketplace has a snippets category where you can find snippets for almost anything.

A lot of Programming Language Pack extensions include snippets also (Python, C#, Go, Java, and C/C++ amongst others).

How do I write my own?

Snippets files are written in JSON. You can also add C-style comments if you wish (technically it is Microsoft's "JSONC" format).

You can create snippets for different scopes: global, workspace, and for a particular language.

To create the snippets file, run the 'Preferences: Configure User Snippets' command, which opens a quickpick dialog as below. Your selection will open a file for editing.

потребителски фрагменти

If you would prefer to write a snippet in a GUI, you can use the snippet generator web app.

фрагмент генератор

Let's look at an example to get familiar with the syntax.

Example

Here is a markdown snippet that comes with VS Code.

{ "Insert heading level 1": { "prefix": "heading1", "body": ["# ${1:${TM_SELECTED_TEXT}}$0"], "description" : "Insert heading level 1" } } 

This snippet inserts a level 1 heading which wraps the markdown around the current selection (if there is one).

A snippet has the following properties:

  1. "Insert heading level 1" is the snippet name. This is the value that is displayed in the IntelliSense suggestion list if no description is provided.
  2. Theprefix property defines the trigger phrase for the snippet. It can be a string or an array of strings (if you want multiple trigger phrases). Substring matching is performed on prefixes, so in this case, typing "h1" would match our example snippet.
  3. The body property is the content that is inserted into the editor. It is an array of strings, which is one or more lines of content. The content is joined together before insertion.
  4. The description property can provide more information about the snippet. It is optional.
  5. The scope property allows you to target specific languages, and you can supply a comma-separated list in the string. It is optional. Of course, it is redundant for a language-specific snippet file.

The body of this snippet has 2 tab stops and uses the variable ${TM_SELECTED_TEXT}.

Let's get into the syntax to understand this fully.

Snippet syntax

VS Code's snippet syntax is the same as the TextMate snippet syntax. However, it does not support 'interpolated shell code' and the use of the \u transformation.

The body of a snippet supports the following features:

1. Tab Stops

Tab stops are specified by a dollar sign and an ordinal number e.g. $1 . $1 will be the first location, $2 will the second location, and so on. $0 is the final cursor position, which exits the snippet mode.

For example, let's say we want to make an HTML div snippet and we want the first tab stop to be between the opening and closing tags. We also want to allow the user to tab outside of the tags to finish the snippet.

Then we could make a snippet like this:

{ "Insert div": { prefix: "div", body: [" ","$1"," ", "$0"] } } 

2. Mirrored Tab Stops

There are times when you need to provide the same value in several places in the inserted text. In these situations you can re-use the same ordinal number for tab stops to signal that you want them mirrored. Then your edits are synced.

A typical example is a for loop which uses an index variable multiple times. Below is a JavaScript example of a for loop.

{ "For Loop": { "prefix": "for", "body": [ "for (let ${1:index} = 0; ${1:index} < ${2:array}.length; ${1:index}++) {", "\tconst ${3:element} = ${2:array}[${1:index}];", "\t$0", "}" ] } } 

3. Placeholders

Placeholders are tab stops with default values. They are wrapped in curly braces, for example ${1:default}. The placeholder text is selected on focus such that it can be easily edited. Placeholders can be nested, like this: ${1:first ${2:second}}.

4. Choices

Choices present the user with a list of values at a tab stop. They are written as a comma-separated list of values enclosed in pipe-characters e.g. $1.

This is the code for the markdown example shown earlier for inserting a task list. The choices are 'x' or a blank space.

{ "Insert task list": { "prefix": "task", "body": ["- [$1] ${2:text}", "${0}"] } 

5. Variables

There is a good selection of variables you can use. You simply prefix the name with a dollar sign to use them, for example $TM_SELECTED_TEXT.

For example, this snippet will create a block comment for any language with today's date:

{ "Insert block comment with date": { prefix: "date comment", body: ["${BLOCK_COMMENT_START}", "${CURRENT_YEAR}/${CURRENT_MONTH}/${CURRENT_DATE} ${1}", "${BLOCK_COMMENT_END}"] } } 

You can specify a default for a variable if you wish, like ${TM_SELECTED_TEXT:default}. If a variable does not have a value assigned, the default or an empty string is inserted.

If you make a mistake and include a variable name that is not defined, the name of the variable is transformed into a placeholder.

The following workspace variables can be used:

  • TM_SELECTED_TEXT: The currently selected text or the empty string,
  • TM_CURRENT_LINE: The contents of the current line,
  • TM_CURRENT_WORD: The contents of the word under cursor or the empty string,
  • TM_LINE_INDEX: The zero-index based line number,
  • TM_LINE_NUMBER: The one-index based line number,
  • TM_FILENAME: The filename of the current document,
  • TM_FILENAME_BASE: The filename of the current document without its extensions,
  • TM_DIRECTORY: The directory of the current document,
  • TM_FILEPATH: The full file path of the current document,
  • CLIPBOARD: The contents of your clipboard,
  • WORKSPACE_NAME: The name of the opened workspace or folder.

The following time-related variables can be used:

  • CURRENT_YEAR: The current year,
  • CURRENT_YEAR_SHORT: The current year's last two digits,
  • CURRENT_MONTH: The month as two digits (example '07'),
  • CURRENT_MONTH_NAME: The full name of the month (example 'July'),
  • CURRENT_MONTH_NAME_SHORT: The short name of the month (example 'Jul'),
  • CURRENT_DATE: The day of the month,
  • CURRENT_DAY_NAME: The name of day (example 'Monday'),
  • CURRENT_DAY_NAME_SHORT: The short name of the day (example 'Mon'),
  • CURRENT_HOUR: The current hour in 24-hour clock format,
  • CURRENT_MINUTE: The current minute,
  • CURRENT_SECOND: The current second,
  • CURRENT_SECONDS_UNIX: The number of seconds since the Unix epoch.

The following comment variables can be used. They honour the syntax of the document's language:

  • BLOCK_COMMENT_START: For example, in HTML,
  • LINE_COMMENT: For example, // in JavaScript.

6. Transformations

Transformations can be applied to a variable or a placeholder. If you are familiar with regular expressions (regex), most of this should be familiar.

The format of a transformation is: ${«variable or placeholder»/«regex»/«replacement string»/«flags»}. It is similar to String.protoype.replace() in JavaScript. The "parameters" do the following:

  • «regex»: This is a regular expression that is matched against the value of the variable or placeholder. The JavaScript regex syntax is supported.
  • «replacement string»: This is the string you want to replace the original text with. It can reference capture groups from the «regex», perform case formatting (using the special functions: /upcase, /downcase, and /capitalize), and perform conditional insertions. See TextMate Replacement String Syntax for more in-depth information.
  • «flags»: Flags that are passed to the regular expression. The JavaScript regex flags can be used:
    • g : Global search,
    • i : Case-insensitive search,
    • m : Multi-line search,
    • s : Allows . to match newline characters,
    • u : Unicode. Treat the pattern as a sequence of Unicode code points,
    • y : Perform a "sticky" search that matches starting at the current position in the target string.

To reference a capture group, use $n where n is the capture group number. Using $0 means the entire match.

This can be a bit confusing since tab stops have the same syntax. Just remember that if it is contained within forward slashes, then it is referencing a capture group.

The easiest way to understand the syntax fully is to check out a few examples.

Snippet bodyInputOutputExplanation
["${TM_SELECTED_TEXT/^.+$/• $0/gm}"]line1

line2

• line1

• line2

Put a bullet point before each non-empty line of the selected text.
["${TM_SELECTED_TEXT/^(\\w+)/${1:/capitalize}/}"]the cat is on the mat.The cat is on the mat.Capitalize the first word of selected text.
["${TM_FILENAME/.*/${0:/upcase}/}"]example.jsEXAMPLE.JSInsert the filename of the current file uppercased.
[

"[",

"${CLIPBOARD/^(.+)$/'$1',/gm}",

"]"

]

line1

line2

['line1', 'line2',]Turn the contents of the clipboard into a string array. Each non-empty line is an element.

As you can see from the second example above, metacharacter sequences must be escaped, for example insert \\w for a word character.

Placeholder Transformations

Placeholder transforms do not allow a default value or choices! Maybe it is more suitable to call them tab stop transformations.

The example below will uppercase the text of the first tab stop.

преобразуване на заместител

{ "Uppercase first tab stop": { "prefix": "up", "body": ["${1/.*/${0:/upcase}/}", "$0"] } } 

You can have a placeholder and perform a transformation on a mirrored instance. The transformation will not be performed on the initial placeholder. ?

Would you use this behaviour somewhere? I find it confusing initially, so it may have the same affect on others.

{ "Uppercase second tab stop instance only": { "prefix": "up", "body": ["${1:title}", "${1/(.*)/${1:/upcase}/}", "$0"] } } 

How do I assign Keyboard Shortcuts for snippets?

By adding your shortcuts to keybindings.json . You can open the file by running the 'Preferences: Open Keyboard Shortcuts File (JSON)' command.

For example, to add a shortcut for the built-in markdown snippet "Insert heading level 1":

{ "key": "ctrl+m ctrl+1", "command": "editor.action.insertSnippet", "when": "editorTextFocus && editorLangId == markdown", "args": { "langId": "markdown", "name": "Insert heading level 1" } } 

You define a shortcut by specifying the key combination you want to use, the command ID, and an optional when clause context for the context when the keyboard shortcut is enabled.

Through the args object, you can target an existing snippet by using the langId and name properties. The langId argument is the language ID of the language that the snippets were written for. The name is the snippet's name as it is defined in the snippet file.

You can define an inline snippet if you wish using the snippet property.

[ { "key": "ctrl+k 1", "command": "editor.action.insertSnippet", "when": "editorTextFocus", "args": { "snippet": "${BLOCK_COMMENT_START}${CURRENT_YEAR}/${CURRENT_MONTH}/${CURRENT_DATE} ${1} ${BLOCK_COMMENT_END}" } } ] 

You can use the Keyboard Shortcuts UI also, but it does not have the ability to add a new shortcut.

Another downside of the UI is that it does not show the args object, which makes it more difficult to find and edit your custom shortcuts. ?

преки пътища-ui

A question of style

Something that I found offputting initially with snippets was the propensity for people to create snippets with abbreviated prefixes. Do I have to learn a big list of gibberish acronyms to use someone else's snippets?

What do I mean by abbreviated prefixes? The table below list a few of the snippets from the JavaScript (ES6) code snippets VS Code extension. You can see in the Trigger column, the prefixes listed are abbreviations, for example fre to represent a "for each" loop.

es6 фрагменти откъс

This is unnecessary in two ways.

Firstly, the quick suggestions offered by VS Code are produced from a fuzzy substring search. If I type "fe" and the prefix of a snippet is "foreach", this will match and be offered as a quick suggestion.

As you can see below, this is the second match.

fe бързо предложение

The first match is fre, which is a snippet from the extension. Which suggestion is more descriptive? ?

If you use the "Insert Snippet" command for snippets, it does not make much of a difference. The description field makes amends for this shortcoming. I don't use snippets in this way, so I would prefer a more descriptive prefix.

вмъкнете фрагмент foreach

Secondly, fre is a duplicate of the built-in snippet foreach.

Some people turn off quick suggestions for snippets and use tab completion only. In this case, you need to type a prefix out without getting visual feedback. Some people may prefer to use an abbreviated prefix to save keystrokes here.

The same fuzzy substring search is being performed in the background, so the first snippet match is inserted when you hit tab.

фрагмент-таб-завършване

Looking at the example above, you can see that typing "fr" and hitting tab inserts the fre snippet. Typing "fore" and hitting tab inserts the foreach snippet.

So, you do not need to type out the entire prefix, if you really don't want to! ? If you have many similarly named snippet prefixes for a language, it would be impractical I imagine.

It is more practical to learn the prefixes properly, and type them out entirely before hitting tab.

There are some trade-offs depending on your preferences for using snippets.

Personally, I like to use quick suggestions as I like the visual feedback. I have snippets set to be the top suggestions, that way I can type abbreviated versions of the prefixes without needing to memorise them.

Some snippet authors have rigid patterns to overcome this, but that's just something I can't get into easily.

If you use a lot of snippets for a language, you may want to choose snippets that are written in a similar style.

If you use snippets for different frameworks and libraries in a language, they can add up and overlap. I haven't needed to do this, but you may need to do it eventually.

Global Snippets

Outside of your code editor, you can benefit from snippets also. Having snippets available in every app offers more possibilities.

Common use cases are:

  • canned responses for messages,
  • autocorrecting common typos,
  • adding contact information or signatures to documents,
  • inserting dates,
  • formatting of selected text and pasted text,
  • inserting search phrases for your search engine or app,
  • HTML snippets available inside your email client,
  • adding different templates to documents.

Most of the apps for snippets are touted as "text expanders", but quite a few task and productivity apps also include snippet-esque features.

Global snippets are bit more limited that code editor snippets, as you cannot use tab stops and placeholders. In most apps you can use some dynamic variables such as dates.

App Review

Autohotkey (Windows)

AutoHotkey is a free, open-source scripting language for Windows to do all kinds of tasks.

It has it's own unique syntax. You can install the AutoHotKey extension to add language support to VS Code for a better editing experience.

For defining prefixes to trigger a snippet insertion, you use the following format: ::<>::<>. The following script will insert Rob's email address when you type "robmail" and hit space or tab or enter.

::robmail::[email protected] 

The following script will insert the text "This is the snippet text" when you press Ctrl+D.

^d:: Send This is the snippet text 

You can read the docs to learn more.

PhraseExpress (Windows, Mac, iOS)

PhraseExpress is "a text expander software, that manages frequently used text templates for insertion into any program".

It is a freemium, GUI-based app. It is aimed at a wider audience than AutoHotKey.

It is quite polished and easy to use. You set it to run on start-up and it will be active in the background.

Your snippets can be organized into custom folders and synced using cloud services.

фраза-експрес

Espanso (Windows, Mac, Linux)

This is a open-source, cross-platform text expander written in Rust.

It uses a file-based configuration approach. The config files are written in YAML.

The default.yml file contains the main configuration. The config below will insert Rob's email address when you type "robmail" .

matches: - trigger: ":robmail" replace: "[email protected]" 

You can specify the initial cursor position, however you cannot define tab stops.

Можете да добавите разширения, за да увеличите възможностите на Espanso. Има разширения за изпълнение на външни скриптове, включително дати, генериране на произволен текст и включително данни от клипборда.

И това е всичко! Надявам се, че сте научили нещо за фрагментите днес и можете да ги използвате, за да станете по-продуктивни.