В этом материале Костя расскажет, как настроить сниппеты — небольшие фрагменты кода, которые можно сохранить в каталог и вставлять по поисковому слову. Если у вас есть какой-то код, который часто повторяете, то его можно добавить в виде сниппета и не печатать каждый раз.
Автор материала
Статью написал Костя @say_hey_to_k — БИМ-специалист из Китая. Он работает на канадскую фирму и, кроме Ревита, занимается также и программированием.
Это третья часть из материала о настройки VSCode, первая была про установку и настройку интерфейса VSCode. Вторая — про подсказки при работе с кодом.
Пример
В предыдущих статьях писал подсказку типа для переменных и методов. Я не писал всю подсказку каждый раз. Как только я начинаю вбивать ty, VSCode мне предлагает два варианта: один для метода, другой - для переменной. После того как я выберу тип подсказки, он вставляет нужную часть текста. А дальше я дописываю типы. Удобно это или нет — решать вам.

Создание файла со сниппетами
Нажимаем Ctr+Shift+P, там вбиваем «snippet» и выбираем «Фрагменты кода: Настройка фрагментов». Если файл со сниппетами у вас уже есть, то предложит его выбрать. Если нет, предложит создать. Выбираем Python.


VSCode создаст нам json файл с закомментированным примером и описанием сниппета.
Если хотите добавить сниппеты для подсказок типа, замените всё следующим кодом и сохранитесь:
{
"Method type comment": {
"prefix": "type for method",
"body": "# type: ($1) -> ${2:None}",
"description": "Adds method type comment in py2 style."
},
"Variable type comment": {
"prefix": "type for variable",
"body": "# type: ",
"description": "Adds variable type comment in py2 style."
},
}
Краткое описание того, что находится в файле сниппетов:

По умолчанию сниппет не всегда будет на самом верху подсказок:

Если хочется, чтобы сниппеты были всегда наверху, идём в параметры VSCode, там вбиваем «snippet suggestions» и выбираем top:

Создание своего сниппета
Если сниппет — простой однострочный текст, то заходим в файл сниппетов, дублируем предыдущий и заполняем необходимые поля. Не игнорируйте подчёркивания ошибок. Возможно, вы накосячили с синтаксисом. Он вам подскажет, если где-то пропущена скобочка, стоит лишняя запятая или ещё чего.
Если сниппет многострочный, можно его предварительно сгенерировать при помощи онлайн сервиса, например snippet-generator. Также в каталоге расширений есть различные плагины для генерации и управления сниппетами. Я использую Easy Snippet. Но это уже излишество. Напомню, чем меньше расширений, тем лучше.
Можно выбирать, как вставляется сниппет, куда переместится курсор при его создании (как например, у меня в сниппете подсказки для метода), сгенерировать всякую инфу и многое другое. Про всё это можно прочитать в справке.
Импорты
Знакомая картина?

Мы создаём мегашаблон с импортами на все случаи жизни, с которого начинаем кодить. Обещаем себе удалить неиспользуемые импорты потом. А может и нет. Зачем?
В итоге каждый раз открывая файл, чтобы добраться до кода, нам нужно промотать всю эту бесполезную простыню. А потом ещё ловим непонятные ошибки вроде «Line object has no attribute ‘CreateBound’».
При работе в VSCode от такой практики можно отказаться, используя подсказки и сниппеты.
Стандартные библиотеки (типа os, re, itertools и даже System.Collections.Generic) VSCode будет и так предлагать импортировать. Часто встречающиеся апишные импорты можно добавлять сниппетами по надобности.
Сначала рассмотрим один пример с самым распространённым импортом. Добавим следующий сниппет и сохранимся:
"Import Autodesk Revit DB": {
"prefix": "import db",
"body": [
"clr.AddReference(\"RevitAPI\")",
"from Autodesk.Revit.DB import *",
""
],
"description": "Imports Autodesk.Revit.DB"
}
Если в коде начнём вбивать “import” или “db”, он его предложит:

Сам я против импорта звёздочки. По многим причинам. У себя в коде стараюсь использовать хотя бы from Autodesk.Revit import DB. Но также знаю, что в динамовских скриптах это очень распространённая практика. Переучивать никого не собираюсь.
Теперь выкатим все сниппеты сразу (можете заменить ими всё в файле со сниппетами или использовать только часть):
{
"Method type comment": {
"prefix": "type for method",
"body": "# type: ($1) -> ${2:None}",
"description": "Adds method type comment in py2 style."
},
"Variable type comment": {
"prefix": "type for variable",
"body": "# type: ",
"description": "Adds variable type comment in py2 style."
},
"UnwrapElement": {
"prefix": "UnwrapElement",
"body": "UnwrapElement(IN[$1])",
"description": "Adds UnwrapElement(IN[])"
},
"Import Autodesk Revit DB": {
"prefix": "import db",
"body": [
"clr.AddReference(\"RevitAPI\")",
"from Autodesk.Revit.DB import *",
""
],
"description": "Imports Autodesk.Revit.DB"
},
"Import Dynamo Revit Nodes ": {
"prefix": "import dynamo elements",
"body": [
"clr.AddReference(\"RevitNodes\")",
"from Revit.Elements import *",
""
],
"description": "Imports Dynamo Node Revit Elements"
},
"Import Dynamo Element Wrapper Extension": {
"prefix": "import element wrapper",
"body": [
"import Revit",
"clr.ImportExtensions(Revit.Elements)",
""
],
"description": [
"Imports ToDSType(bool) extension method.",
"",
"Requires imported RevitNodes: clr.AddReference(\"RevitNodes\")",
""
]
},
"Import Dynamo Geometry Wrapper Extension": {
"prefix": "import geometry wrapper",
"body": [
"import Revit",
"clr.ImportExtensions(Revit.GeometryConversion)",
""
],
"description": [
"Imports ToProtoType(), ToRevitType() geometry extension methods.",
"",
"Requires imported RevitNodes: clr.AddReference(\"RevitNodes\")",
""
]
},
"Import Dynamo Proto Geometry": {
"prefix": "import dynamo proto geometry",
"body": [
"clr.AddReference(\"ProtoGeometry\")",
"from Autodesk.DesignScript.Geometry import *",
""
],
"description": "Imports Dynamo Proto Geometry"
},
"Import Dynamo RevitServices": {
"prefix": "import doc tran manager",
"body": [
"clr.AddReference(\"RevitServices\")",
"from RevitServices.Persistence import DocumentManager",
"from RevitServices.Transactions import TransactionManager",
""
],
"description": [
"Imports Dynamo Revit Services",
"(DocumentManager and TransactionManager)",
""
]
},
"CurrentDBDocument": {
"prefix": "doc",
"body": [
"doc = DocumentManager.Instance.CurrentDBDocument",
""
],
"description": [
"Assigns CurrentDBDocument to variable doc",
"",
"Requires imported RevitServices and DocumentManager from RevitServices",
""
]
},
"CurrentUIApplication": {
"prefix": "uiapp",
"body": [
"uiapp = DocumentManager.Instance.CurrentUIApplication",
""
],
"description": [
"Assigns CurrentUIApplication to variable uiapp",
"",
"Requires imported RevitServices and DocumentManager from RevitServices",
""
]
},
"CurrentUIApplication Application": {
"prefix": "app",
"body": [
"app = DocumentManager.Instance.CurrentUIApplication.Application",
""
],
"description": [
"Assigns CurrentUIApplication.Application to variable app",
"",
"Requires imported RevitServices and DocumentManager from RevitServices",
""
]
}
}
Как с этим работать (когда привыкнете, ваша скорость будет намного выше):

Логика следующая: вы не храните абсолютно всё в шаблоне. В шаблоне должно быть только то, с чего начинается 99 % вашего любого кода. Импорты добавляете сниппетами по надобности, вбивая любую часть триггер-слова. Триггеры у сниппетов могут повторяться. По подсказкам можно листать, читая подробные описания (если вы их туда добавили). Все подсказки можно вывести, нажав Ctrl + Пробел.
Возможно, по иллюстрации вы заметили, что я добавил сниппет «UnwrapElement». Можете подумать, какие ещё часто встречающиеся куски кода у вас есть и записать их в сниппеты.
Удачи!



