diff --git a/tools/brick_generator/README.md b/tools/brick_generator/README.md index c8b20d0..f0050f9 100644 --- a/tools/brick_generator/README.md +++ b/tools/brick_generator/README.md @@ -1,5 +1,5 @@ -A sample command-line application to generate which allows to generate the template of a brick from a project which compiles. with an entrypoint in `bin/`, library code -in `lib/`. +A sample command-line application to generate which allows to generate the template of a brick from a project which compiles. +With an entrypoint in `bin/`, library code in `lib/`. # How to use @@ -15,18 +15,6 @@ variables: feature_brick: variable_name: feature_brick type: string - syntax: - camel_case: featureBrick - constant_case: FEATURE_BRICK - dot_case: feature.brick - header_case: Feature-Brick - lower_case: feature brick - pascal_case: FeatureBrick - param_case: feature-brick - sentence_case: Feature brick - snake_case: feature_brick - title_case: Feature Brick - upper_case: FEATURE BRICK isBloc: variable_name: bloc type: bool diff --git a/tools/brick_generator/bin/brick_generator.dart b/tools/brick_generator/bin/brick_generator.dart index b8d917e..a96c5ef 100644 --- a/tools/brick_generator/bin/brick_generator.dart +++ b/tools/brick_generator/bin/brick_generator.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:brick_generator/file_system_utils.dart'; +import 'package:brick_generator/logger.dart'; import 'package:brick_generator/models/brick_config.dart'; import 'package:brick_generator/shell.dart'; import 'package:brick_generator/yaml_reader.dart'; @@ -10,11 +11,13 @@ import 'package:path/path.dart' as path; const _bricks = 'bricks'; const _brickFolderLabel = '__brick__'; const _yamlFileName = 'brick_config.yaml'; +const _cfgFileName = 'brick.yaml'; Future main(List arguments) async { try { if (arguments.length != 1) { - throw ArgumentError('Please entry exemple project path'); + Logger.error('Please provide project path.'); + exit(1); } final projectPath = arguments[0]; @@ -23,7 +26,7 @@ Future main(List arguments) async { final configs = YamlReader.readYamlFile(path.join(projectPath, _yamlFileName)); final brickConfig = BrickConfig.from(configs); - stdout.writeln('🍺 config retrieved'); + Logger.info('Config retrieved.'); brickConfig?.checkFormat(); @@ -32,12 +35,17 @@ Future main(List arguments) async { projectPath, brickConfig!.pathToBrickify, ); + final cfgTarget = path.join( + _bricks, + brickConfig.name, + _cfgFileName, + ); final targetPath = path.join( _bricks, - brickConfig.brickName, + brickConfig.name, _brickFolderLabel, ); - stdout.writeln('🍺 path defined'); + Logger.info('Path defined.'); // Remove previously generated files final targetDir = Directory(targetPath); @@ -45,27 +53,37 @@ Future main(List arguments) async { await targetDir.delete(recursive: true); } + final cfgTargetFile = File(cfgTarget); + if (cfgTargetFile.existsSync()) { + await cfgTargetFile.delete(); + } + // create target folder await Shell.mkdir(targetPath); // Copy project files await Shell.cp(sourcePath, targetPath); - stdout.writeln('🍺 files copied'); + Logger.info('Files copied.'); // Convert values to variables await FileSystemUtils.convertValuesToVariablesInFolder( - brickConfig, targetPath); - stdout.writeln('🍺 values converted into variables'); + brickConfig, + targetPath, + ); + Logger.info('Values converted into variables.'); // Rename files and folders await FileSystemUtils.renamePathsInFolder(brickConfig, targetPath); - stdout.writeln('🍺 folders and files renamed'); + Logger.info('Folders and files renamed.'); + + // Create config file + cfgTargetFile.writeAsStringSync(brickConfig.toBrickYaml()); + Logger.info('brick.yml added.'); await FileSystemUtils.deleteEmptyFolders(targetPath); - stdout - ..writeln('🍺 empty folders removed') - ..writeln('✅ brick template available at $targetPath'); - } catch (_) { - stdout.writeln('❌ ${_.toString()}'); + Logger.info('Empty folders removed'); + Logger.success('Brick template available at $targetPath'); + } catch (e) { + Logger.error(e); } } diff --git a/tools/brick_generator/lib/file_system_utils.dart b/tools/brick_generator/lib/file_system_utils.dart index e768a4f..8c7fa6e 100644 --- a/tools/brick_generator/lib/file_system_utils.dart +++ b/tools/brick_generator/lib/file_system_utils.dart @@ -1,5 +1,22 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + import 'dart:io'; +import 'package:brick_generator/logger.dart'; import 'package:brick_generator/models/brick_config.dart'; import 'package:brick_generator/models/variable_string_syntax.dart'; import 'package:brick_generator/models/variable_type.dart'; @@ -22,9 +39,9 @@ class FileSystemUtils { if (brickConfig.variables != null) { for (final variable in brickConfig.variables!) { // Replace all string variables - if (variable?.type == VariabelType.string) { + if (variable?.type == VariableType.string) { for (final syntax in VariableStringSyntax.values) { - final toReplace = variable?.syntax?[syntax.mapKey] as String?; + final toReplace = variable?.syntax?[syntax.mapKey]; if (toReplace != null) { contents = contents.replaceAll( toReplace, @@ -33,9 +50,7 @@ class FileSystemUtils { } } } - stdout.writeln( - '🍺 variables ${variable?.name} added in ${file.path}', - ); + Logger.info('Variable ${variable?.name} added in ${file.path}'); } } @@ -59,12 +74,17 @@ class FileSystemUtils { // Rename file if needed if (brickConfig.variables != null) { for (final variable in brickConfig.variables!) { - if (variable?.type == VariabelType.string && + if (variable?.type == VariableType.string && variable?.syntax?[VariableStringSyntax.snakeCase.mapKey] != null) { + final snake = + variable!.syntax![VariableStringSyntax.snakeCase.mapKey]; + if (snake == null) { + final err = 'Invalid snake_case syntax'; + Logger.throwError(ArgumentError(err), err); + } final newPath = file.path.replaceAll( - variable!.syntax![VariableStringSyntax.snakeCase.mapKey] - as String, + snake!, '{{${variable.name}.snakeCase()}}', ); @@ -80,7 +100,7 @@ class FileSystemUtils { static Future deleteEmptyFolders(String path) async { for (final dir in Directory(path).listSync(recursive: true).reversed) { if (dir is Directory) { - if (await dir.exists() && await dir.list().isEmpty) { + if (dir.existsSync() && await dir.list().isEmpty) { await dir.delete(recursive: true); } } diff --git a/tools/brick_generator/lib/logger.dart b/tools/brick_generator/lib/logger.dart new file mode 100644 index 0000000..1f46e4e --- /dev/null +++ b/tools/brick_generator/lib/logger.dart @@ -0,0 +1,49 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'dart:io'; + +import 'package:brick_generator/models/log_level.dart'; + +class Logger { + static void log(Object? message, {LogLevel level = LogLevel.info}) { + stdout.writeln('${level.prefix} ${message.toString()}'); + } + + static void info(Object? message) { + log(message); + } + + static void error(Object? message) { + log(message, level: LogLevel.error); + } + + static void success(Object? message) { + log(message, level: LogLevel.success); + } + + static void throwError(Object error, [Object? message]) { + assert( + error is Exception || error is Exception, + 'Only throw instances of classes extending either Exception or Error;', + ); + if (message != null) { + Logger.error(message); + } + // ignore: only_throw_errors + throw error; + } +} diff --git a/tools/brick_generator/lib/models/brick_config.dart b/tools/brick_generator/lib/models/brick_config.dart index e1ce248..d719745 100644 --- a/tools/brick_generator/lib/models/brick_config.dart +++ b/tools/brick_generator/lib/models/brick_config.dart @@ -1,17 +1,40 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:brick_generator/logger.dart'; import 'package:brick_generator/models/brick_variable.dart'; import 'package:yaml/yaml.dart'; -const _brickNameKey = 'brick_name'; +const _nameKey = 'name'; +const _descriptionKey = 'description'; +const _versionKey = 'version'; const _pathToBrickifyKey = 'path_to_brickify'; -const _variablesKey = 'variables'; +const _varsKey = 'vars'; class BrickConfig { - String? brickName; + String? name; + String? description; + String? version; String? pathToBrickify; List? variables; BrickConfig({ - required this.brickName, + required this.name, + required this.description, + required this.version, required this.pathToBrickify, required this.variables, }); @@ -21,9 +44,11 @@ class BrickConfig { static BrickConfig? from(YamlMap? data) => data != null ? BrickConfig( - brickName: data[_brickNameKey] as String?, + name: data[_nameKey] as String?, + description: data[_descriptionKey] as String?, + version: data[_versionKey] as String?, pathToBrickify: data[_pathToBrickifyKey] as String?, - variables: (data[_variablesKey] as YamlMap?) + variables: (data[_varsKey] as YamlMap?) ?.map( (dynamic key, dynamic value) => MapEntry( @@ -37,10 +62,9 @@ class BrickConfig { : null; void checkFormat() { - if (brickName == null || pathToBrickify == null) { - throw ArgumentError( - 'Yaml file is not conform', - ); + if (name == null || description == null || pathToBrickify == null) { + final err = 'Yaml file is not conform'; + Logger.throwError(ArgumentError(err), err); } if (variables != null) { for (final variable in variables!) { @@ -48,4 +72,35 @@ class BrickConfig { } } } + + String toBrickYaml() { + String content = ''' +name: $name +description: $description + +version: $version + +environment: + mason: ">=0.1.0-dev.26 <0.1.0" + +'''; + + if (variables?.isNotEmpty ?? false) { + content += 'vars:\n'; + for (final BrickVariable? v in variables!) { + if (v != null) { + final vString = ''' + ${v.name}: + type: ${v.type.toString()} + description: ${v.description} + default: ${v.defaultValue} + prompt: ${v.prompt} +'''; + content += vString; + } + } + } + + return content; + } } diff --git a/tools/brick_generator/lib/models/brick_variable.dart b/tools/brick_generator/lib/models/brick_variable.dart index a34e704..ea75004 100644 --- a/tools/brick_generator/lib/models/brick_variable.dart +++ b/tools/brick_generator/lib/models/brick_variable.dart @@ -1,18 +1,44 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:brick_generator/logger.dart'; import 'package:brick_generator/models/variable_type.dart'; +import 'package:brick_generator/string_extension.dart'; import 'package:yaml/yaml.dart'; -const _variableNameKey = 'variable_name'; const _typeKey = 'type'; -const _syntaxKey = 'syntax'; +const _nameKey = 'name'; +const _descriptionKey = 'description'; +const _defaultKey = 'default'; +const _promptKey = 'prompt'; class BrickVariable { + VariableType? type; String? name; - VariabelType? type; - YamlMap? syntax; + String? description; + String? defaultValue; + String? prompt; + Map? syntax; BrickVariable({ - required this.name, required this.type, + required this.name, + required this.description, + required this.defaultValue, + required this.prompt, required this.syntax, }); @@ -22,17 +48,19 @@ class BrickVariable { static BrickVariable? from(YamlMap? data) => data != null ? BrickVariable( - name: data[_variableNameKey] as String?, - type: VariabelType.stringToEnum(data[_typeKey] as String?), - syntax: data[_syntaxKey] as YamlMap?, + type: VariableType.fromString(data[_typeKey] as String?), + name: data[_nameKey] as String?, + description: data[_descriptionKey] as String?, + defaultValue: data[_defaultKey] as String?, + prompt: data[_promptKey] as String?, + syntax: (data[_nameKey] as String? ?? '').syntaxes, ) : null; void checkFormat() { - if (name == null || type == null) { - throw ArgumentError( - 'Yaml file is not conform', - ); + if (name == null || description == null || type == null) { + final err = 'Yaml file is not conform'; + Logger.throwError(ArgumentError(err), err); } } } diff --git a/tools/brick_generator/lib/models/log_level.dart b/tools/brick_generator/lib/models/log_level.dart new file mode 100644 index 0000000..ea214a5 --- /dev/null +++ b/tools/brick_generator/lib/models/log_level.dart @@ -0,0 +1,25 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +enum LogLevel { + info('🍺'), + success('✅'), + error('❌'); + + final String prefix; + + const LogLevel(this.prefix); +} diff --git a/tools/brick_generator/lib/models/variable_string_syntax.dart b/tools/brick_generator/lib/models/variable_string_syntax.dart index 053bace..daa840e 100644 --- a/tools/brick_generator/lib/models/variable_string_syntax.dart +++ b/tools/brick_generator/lib/models/variable_string_syntax.dart @@ -1,3 +1,19 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + enum VariableStringSyntax { snakeCase('snake_case', 'snakeCase'), camelCase('camel_case', 'camelCase'), diff --git a/tools/brick_generator/lib/models/variable_type.dart b/tools/brick_generator/lib/models/variable_type.dart index db6aef6..29d99a9 100644 --- a/tools/brick_generator/lib/models/variable_type.dart +++ b/tools/brick_generator/lib/models/variable_type.dart @@ -1,9 +1,25 @@ -enum VariabelType { +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +enum VariableType { none, string, bool; - static VariabelType stringToEnum(String? type) { + static VariableType fromString(String? type) { switch (type) { case 'string': return string; @@ -13,4 +29,9 @@ enum VariabelType { return none; } } + + @override + String toString() { + return name; + } } diff --git a/tools/brick_generator/lib/shell.dart b/tools/brick_generator/lib/shell.dart index e16b30f..d3b2199 100644 --- a/tools/brick_generator/lib/shell.dart +++ b/tools/brick_generator/lib/shell.dart @@ -1,5 +1,23 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + import 'dart:io'; +import 'package:brick_generator/logger.dart'; + class Shell { static Future cp(String source, String destination) { return _Cmd.run('cp', ['-Rf', source, destination]); @@ -50,7 +68,10 @@ class _Cmd { message = values.entries.map((e) => '${e.key}\n${e.value}').join('\n'); } - throw ProcessException(process, args, message, pr.exitCode); + Logger.throwError( + ProcessException(process, args, message, pr.exitCode), + message, + ); } } } diff --git a/tools/brick_generator/lib/string_extension.dart b/tools/brick_generator/lib/string_extension.dart new file mode 100644 index 0000000..3b51873 --- /dev/null +++ b/tools/brick_generator/lib/string_extension.dart @@ -0,0 +1,283 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +extension StringExtension on String { + static final RegExp _defaultMatcher = RegExp(r'\s+|-+|_+|\.+'); + + Map get syntaxes => { + 'camel_case': camel(), + 'constant_case': constant(), + 'dot_case': dot(), + 'header_case': header(), + 'lower_case': lower(), + 'pascal_case': pascal(), + 'param_case': param(), + 'sentence_case': sentence(), + 'title_case': title(), + 'upper_case': upper(), + 'snake_case': snake(), + }; + + /// ```dart + /// print('abcd'.capitalize()) // Abcd + /// print('Abcd'.capitalize()) // Abcd + /// ``` + String capitalize() { + switch (length) { + case 0: + return this; + case 1: + return toUpperCase(); + default: + return substring(0, 1).toUpperCase() + substring(1); + } + } + + /// ```dart + /// print('abcd'.decapitalize()) // abcd + /// print('Abcd'.decapitalize()) // abcd + /// ``` + String decapitalize() { + switch (length) { + case 0: + return this; + case 1: + return toLowerCase(); + default: + return substring(0, 1).toLowerCase() + substring(1); + } + } + + /// ```dart + /// print('Hello-world'.camel()) // helloWorld + /// print('hello_World'.camel()) // helloWorld + /// print('Hello World'.camel()) // helloWorld + /// print('helloWorld'.camel()) // helloWorld + /// print('long space'.camel()) // longSpace + /// ``` + String camel() { + if (length > 0) { + return pascal().decapitalize(); + } else { + return this; + } + } + + /// ```dart + /// print('Hello World'.pascal()) // HelloWorld + /// print('helloWorld'.pascal()) // HelloWorld + /// print('long space'.pascal()) // LongSpace + /// ``` + String pascal() { + switch (length) { + case 0: + return this; + case 1: + return toUpperCase(); + default: + return splitMapJoin( + _defaultMatcher, + onMatch: (m) => '', + onNonMatch: (n) => n.capitalize(), + ); + } + } + + /// ```dart + /// print('Hello World'.constant()) // HELLO_WORLD + /// print('helloWorld'.constant()) // HELLO_WORLD + /// print('long space'.constant()) // LONG_SPACE + /// ``` + String constant() { + switch (length) { + case 0: + return this; + case 1: + return toUpperCase(); + default: + return splitMapJoin( + RegExp('[A-Z]'), + onMatch: (m) => ' ${m[0]}', + onNonMatch: (n) => n, + ).trim().splitMapJoin( + _defaultMatcher, + onMatch: (m) => '_', + onNonMatch: (n) => n.toUpperCase(), + ); + } + } + + /// ```dart + /// print('Hello World'.dot()) // hello.world + /// print('helloWorld'.dot()) // hello.world + /// print('long space'.dot()) // long.space + /// ``` + String dot() { + switch (length) { + case 0: + return this; + case 1: + return toLowerCase(); + default: + return splitMapJoin( + RegExp('[A-Z]'), + onMatch: (m) => ' ${m[0]}', + onNonMatch: (n) => n, + ).trim().splitMapJoin( + _defaultMatcher, + onMatch: (m) => '.', + onNonMatch: (n) => n.toLowerCase(), + ); + } + } + + /// ```dart + /// print('Hello World'.header()) // Hello-World + /// print('helloWorld'.header()) // Hello-World + /// ``` + String header() { + switch (length) { + case 0: + return this; + case 1: + return toUpperCase(); + default: + return splitMapJoin( + RegExp('[A-Z]'), + onMatch: (m) => ' ${m[0]}', + onNonMatch: (n) => n.toLowerCase(), + ).trim().splitMapJoin( + _defaultMatcher, + onMatch: (m) => '-', + onNonMatch: (n) => n.capitalize(), + ); + } + } + + /// ```dart + /// print('Hello World'.lower()) // hello world + /// print('helloWorld'.lower()) // hello world + /// ``` + String lower() { + switch (length) { + case 0: + return this; + case 1: + return toLowerCase(); + default: + return splitMapJoin( + RegExp('[A-Z]'), + onMatch: (m) => ' ${m[0]}', + onNonMatch: (n) => n, + ).trim().splitMapJoin( + _defaultMatcher, + onMatch: (m) => ' ', + onNonMatch: (n) => n.toLowerCase(), + ); + } + } + + /// ```dart + /// print('Hello World'.param()) // hello-world + /// print('helloWorld'.param()) // hello-world + /// print('long space'.param()) // long-space + /// ``` + String param() { + switch (length) { + case 0: + return this; + case 1: + return toLowerCase(); + default: + return splitMapJoin( + RegExp('[A-Z]'), + onMatch: (m) => ' ${m[0]}', + onNonMatch: (n) => n, + ).trim().splitMapJoin( + _defaultMatcher, + onMatch: (m) => '-', + onNonMatch: (n) => n.toLowerCase(), + ); + } + } + + /// ```dart + /// print('Hello World'.upper()) // HELLO WORLD + /// print('helloWorld'.upper()) // HELLO WORLD + /// ``` + String upper() { + switch (length) { + case 0: + return this; + case 1: + return toUpperCase(); + default: + return splitMapJoin( + RegExp('[A-Z]'), + onMatch: (m) => ' ${m[0]}', + onNonMatch: (n) => n, + ).trim().splitMapJoin( + _defaultMatcher, + onMatch: (m) => ' ', + onNonMatch: (n) => n.toUpperCase(), + ); + } + } + + /// ```dart + /// print('Hello World'.snake()) // hello_world + /// print('helloWorld'.snake()) // hello_world + /// print('long space'.snake()) // long_space + /// ``` + String snake() { + switch (length) { + case 0: + return this; + case 1: + return toLowerCase(); + default: + return splitMapJoin( + RegExp('[A-Z]'), + onMatch: (m) => ' ${m[0]}', + onNonMatch: (n) => n, + ).trim().splitMapJoin( + _defaultMatcher, + onMatch: (m) => '_', + onNonMatch: (n) => n.toLowerCase(), + ); + } + } + + /// ```dart + /// print('Hello World'.sentence()) // Hello world + /// print('helloWorld'.sentence()) // Hello world + /// ``` + String sentence() { + return lower().capitalize(); + } + + /// ```dart + /// print('Hello World'.title()) // Hello World + /// print('helloWorld'.title()) // Hello World + /// ``` + String title() { + return header().splitMapJoin( + _defaultMatcher, + onMatch: (m) => ' ', + onNonMatch: (n) => n, + ); + } +} diff --git a/tools/brick_generator/lib/yaml_reader.dart b/tools/brick_generator/lib/yaml_reader.dart index a7bdf15..b154f02 100644 --- a/tools/brick_generator/lib/yaml_reader.dart +++ b/tools/brick_generator/lib/yaml_reader.dart @@ -1,3 +1,19 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + import 'dart:io'; import 'package:yaml/yaml.dart'; diff --git a/tools/brick_generator/pubspec.yaml b/tools/brick_generator/pubspec.yaml index 3ecdbc3..52d38a9 100644 --- a/tools/brick_generator/pubspec.yaml +++ b/tools/brick_generator/pubspec.yaml @@ -12,6 +12,7 @@ dependencies: yaml: ^3.1.1 dev_dependencies: + test: ^1.22.2 wyatt_analysis: git: url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages diff --git a/tools/brick_generator/test/string_test.dart b/tools/brick_generator/test/string_test.dart new file mode 100644 index 0000000..8275a26 --- /dev/null +++ b/tools/brick_generator/test/string_test.dart @@ -0,0 +1,53 @@ +// Copyright (C) 2023 WYATT GROUP +// Please see the AUTHORS file for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +import 'package:brick_generator/string_extension.dart'; +import 'package:test/test.dart'; + +void main() { + final expected = { + 'camel_case': 'featureName', + 'constant_case': 'FEATURE_NAME', + 'dot_case': 'feature.name', + 'header_case': 'Feature-Name', + 'lower_case': 'feature name', + 'pascal_case': 'FeatureName', + 'param_case': 'feature-name', + 'sentence_case': 'Feature name', + 'title_case': 'Feature Name', + 'upper_case': 'FEATURE NAME', + 'snake_case': 'feature_name', + }; + test('transforms `feature_name`', () { + final name = 'feature_name'; + expect(name.syntaxes, equals(expected)); + }); + + test('transforms `featureName`', () { + final name = 'feature_name'; + expect(name.syntaxes, equals(expected)); + }); + + test('transforms `feature-Name`', () { + final name = 'feature_name'; + expect(name.syntaxes, equals(expected)); + }); + + test('transforms `Feature Name`', () { + final name = 'feature_name'; + expect(name.syntaxes, equals(expected)); + }); +}