Полезные Snippets для Flutter-разработчика

от автора

Всем привет! На связи Глеб Гусаров, flutter-разработчик в команде aim digital. Мы занимаемся разработкой цифровых продуктов и сервисов и автоматизацией процессов для бизнеса. В статье рассказываю, как создать файл конфигурации сниппетов и делюсь своей подборкой полезных сниппетов.

Snippet — это шаблон (подсказка в коде), по вызову которого можно быстро вставить готовый код.

В файле конфигурации сниппет представляет собой сущность в JSON имеющую ключ состоящую из двух полей:

  1. поле prefix — тип данных String — ключевое слово, при написании которого будет предложено использовать snippet

  2. поле body — массив String — код, который будет вставлен после применения snippet’a

Пример snippet’a :

"localizationImport": {     "prefix": "localizationImport",     "body": [         "import 'package:perfluence_app/generated/l10n.dart';",      ], }

Специальные возможности и регулярные выражения в snippet’ах

«\t» — табуляция.

«$1» — место куда будет поставлен курсор после применения snippet’a, можно использовать $2, $3 и т.д. Цифра — это очередность позиции, куда встанет курсор после нажатия на Tab.

«$TM_FILENAME_BASE» — обращение к названию файла без расширения.

«${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}» — вернет название файла в CamelCase.

Как создать файл конфигурации Snippet’ов

  1. В Visual Studio code нажать комбинацию клавиш cmnd(ctrl) + shift + p   

  2. В появившемся поле ввести — Snippets 

  3. Выбрать в выпадающем меню пункт Preferences: Configure User Snippets и нажать Enter 

  4. Выбрать расширение файла, для которого будут использованы Snippet’ы (В нашем случае файлы с расширением .dart).  После чего создастся json-файл конфигурации Snippet’ов.

Примеры полезных сниппетов

Шаблон для дата классов (десериализация json_annotation +  equatable)

"dataClassFrom": {     "prefix": "dataClassFrom",      "body": [          "import 'package:equatable/equatable.dart';",         "import 'package:json_annotation/json_annotation.dart';",         "",         "part '$TM_FILENAME_BASE.g.dart';",         "",         "@JsonSerializable(",         "\tfieldRename: FieldRename.snake,",         "\tcreateToJson: false,",         ")",         "",         "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g} extends Equatable{",         "\tconst ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}();",         "",         "\tfactory ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}.fromJson(Map<String, dynamic> json) => _$${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}FromJson(json);",         "",         "\t$1",         "",         "\t@override",         "\tList<Object?> get props => [];",         "}",      ] },

Шаблон для дата классов (десериализация, сериализация json_annotation +  equatable)

"dataClassToFrom": {     "prefix": "dataClassToFrom",     "body": [          "import 'package:equatable/equatable.dart';",         "import 'package:json_annotation/json_annotation.dart';",         "",         "part '$TM_FILENAME_BASE.g.dart';",         "",         "@JsonSerializable(",         "\tfieldRename: FieldRename.snake,",         ")",         "",         "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g} extends Equatable{",         "\tconst ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}();",         "",         "\tfactory ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}.fromJson(Map<String, dynamic> json) => _$${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}FromJson(json);",         "",         "\tMap<String, dynamic> toJson() => _$${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}ToJson(this);",         "",         "\t$1",         "",         "\t@override",         "\tList<Object?> get props => [];",         "}",      ] },

Шаблон Stateless widget

"stateless": { "prefix": "stless", "body": [ "import 'package:flutter/material.dart';", "", "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends StatelessWidget {", "\t@override", "\tWidget build(BuildContext context) {", "\t\treturn $1;", "\t}", "}",  ]   },

Шаблон Statefull widget

"statefull": { "prefix": "stfull", "body": [ "import 'package:flutter/material.dart';", "", "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/} extends StatefulWidget {", "\t@override", "\tState<${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}> createState() => _${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}State();", "}", "", "class _${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}State extends State<${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/}> {", "\t@override", "\tWidget build(BuildContext context) {", "\t\treturn $2;", "\t}", "}", ] },

Шаблон для быстрого создания цвета из HEX

"color": {       "prefix": "color",       "body": "const Color(0xFF$1)", },

Шаблон для быстрого создания BoxShadow

"boxShadow": {       "prefix": "bsh",       "body": [              "BoxShadow(",              "\tcolor: Colors.black.withOpacity(.5),",              "\toffset: const Offset(0, 0),",              "\tblurRadius: 0,",              "),"        ] },

Шаблон для написания тестов arrange, act, assert 

"aaaTest": {     "prefix": "aaaTest",     "body": [         "test(",          "\t'should $1',",         "\t() async {",         "\t//arrange",         "\t$2",         "\t//act",         "\t",         "\t//assert",         "\t},",         ");",     ], },

Шаблон для создания интерфейса репозитория

"repo": {    "prefix": "repo",    "body": [       "import '/core/error/failures.dart';",       "import 'package:dartz/dartz.dart';",       "",       "abstract class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g} {",       "\t$2",       "}",     ], },

Шаблон для написания имплементации репозитория 

"repoImpl": {     "prefix": "repoImpl",    "body": [       "import 'package:dartz/dartz.dart';",       "import '/core/error/failures.dart';",       "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g} implements $1 {",       "\t@override",       "\tFuture<Either<Failure, $2>> getConcreteNumberTrivia() async {",       "\t\treturn const Left(DefaultFailure());",       "\t}",       "}",     ], },

Шаблон для создания дата-класса параметров usecase

"usecaseParams": {    "prefix": "usecaseParams",    "body": [       "import 'package:dartz/dartz.dart';",       "import 'package:equatable/equatable.dart';",       "import '/core/error/failures.dart';",       "import '/core/usecases/usecase.dart';",       "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}UC implements UseCase<$1, ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}Params> {",       "\tconst ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}UC(this.repo);",       "",       "\tfinal $2 repo;",       "",       "\t@override",       "\tFuture<Either<Failure, $1>> call(${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}Params params) async {",       "\t\treturn await repo.$3();",       "\t}",       "}",       "",       "class ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}Params extends Equatable {",       "\tconst ${TM_FILENAME_BASE/(.*)/${1:/pascalcase}/g}Params();",       "\t@override",        "\tList<Object?> get props => [];",       "}",     ] },  


ссылка на оригинал статьи https://habr.com/ru/articles/736444/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *