diff --git a/packages/flutter_tools/lib/src/base/utils.dart b/packages/flutter_tools/lib/src/base/utils.dart index e7f5412e7c4..62a9b8f1d18 100644 --- a/packages/flutter_tools/lib/src/base/utils.dart +++ b/packages/flutter_tools/lib/src/base/utils.dart @@ -13,6 +13,21 @@ String calculateSha(File file) { return CryptoUtils.bytesToHex(sha1.close()); } +/// Convert `foo_bar` to `fooBar`. +String camelCase(String str) { + int index = str.indexOf('_'); + while (index != -1 && index < str.length - 2) { + str = str.substring(0, index) + + str.substring(index + 1, index + 2).toUpperCase() + + str.substring(index + 2); + index = str.indexOf('_'); + } + return str; +} + +/// Return the plural of the given word (`cat(s)`). +String pluralize(String word, int count) => count == 1 ? word : word + 's'; + /// A class to maintain a list of items, fire events when items are added or /// removed, and calculate a diff of changes when a new list of items is /// available. diff --git a/packages/flutter_tools/lib/src/commands/create.dart b/packages/flutter_tools/lib/src/commands/create.dart index 3449dd214e6..020d944f851 100644 --- a/packages/flutter_tools/lib/src/commands/create.dart +++ b/packages/flutter_tools/lib/src/commands/create.dart @@ -10,6 +10,7 @@ import 'package:path/path.dart' as path; import '../android/android.dart' as android; import '../artifacts.dart'; +import '../base/utils.dart'; import '../dart/pub.dart'; import '../globals.dart'; import '../template.dart'; @@ -87,8 +88,10 @@ class CreateCommand extends Command { _renderTemplates(projectName, dirPath, flutterPackagesDirectory, renderDriverTest: argResults['with-driver-test']); + printStatus(''); + if (argResults['pub']) { - int code = await pubGet(directory: projectDir.path); + int code = await pubGet(directory: dirPath); if (code != 0) return code; } @@ -103,7 +106,7 @@ class CreateCommand extends Command { printStatus(''' All done! In order to run your application, type: - \$ cd ${projectDir.path} + \$ cd $dirPath \$ flutter run '''); } else { @@ -116,7 +119,7 @@ All done! In order to run your application, type: printStatus(''); printStatus("After installing components, run 'flutter doctor' in order to " "re-validate your setup."); - printStatus("When complete, type 'flutter run' from the '${projectDir.path}' " + printStatus("When complete, type 'flutter run' from the '$dirPath' " "directory in order to launch your app."); } @@ -125,7 +128,6 @@ All done! In order to run your application, type: void _renderTemplates(String projectName, String dirPath, String flutterPackagesDirectory, { bool renderDriverTest: false }) { - String projectIdentifier = _createProjectIdentifier(path.basename(dirPath)); String relativeFlutterPackagesDirectory = path.relative(flutterPackagesDirectory, from: dirPath); printStatus('Creating project ${path.basename(projectName)}:'); @@ -134,7 +136,8 @@ All done! In order to run your application, type: Map templateContext = { 'projectName': projectName, - 'projectIdentifier': projectIdentifier, + 'androidIdentifier': _createAndroidIdentifier(projectName), + 'iosIdentifier': _createUTIIdentifier(projectName), 'description': description, 'flutterPackagesDirectory': relativeFlutterPackagesDirectory, 'androidMinApiLevel': android.minApiLevel @@ -163,11 +166,15 @@ String _normalizeProjectName(String name) { return name; } -String _createProjectIdentifier(String name) { +String _createAndroidIdentifier(String name) { + return 'com.yourcompany.${camelCase(name)}'; +} + +String _createUTIIdentifier(String name) { // Create a UTI (https://en.wikipedia.org/wiki/Uniform_Type_Identifier) from a base name RegExp disallowed = new RegExp(r"[^a-zA-Z0-9\-.\u0080-\uffff]+"); - name = name.replaceAll(disallowed, ''); - name = name.length == 0 ? 'untitled' : name; + name = camelCase(name).replaceAll(disallowed, ''); + name = name.isEmpty ? 'untitled' : name; return 'com.yourcompany.$name'; } diff --git a/packages/flutter_tools/lib/src/commands/devices.dart b/packages/flutter_tools/lib/src/commands/devices.dart index a6611e400af..b5b1a09cbef 100644 --- a/packages/flutter_tools/lib/src/commands/devices.dart +++ b/packages/flutter_tools/lib/src/commands/devices.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import '../base/utils.dart'; import '../device.dart'; import '../globals.dart'; import '../runner/flutter_command.dart'; @@ -38,5 +39,3 @@ class DevicesCommand extends FlutterCommand { return 0; } } - -String pluralize(String word, int count) => count == 1 ? word : word + 's'; diff --git a/packages/flutter_tools/lib/src/commands/run.dart b/packages/flutter_tools/lib/src/commands/run.dart index 77ffcad9829..620f4733df6 100644 --- a/packages/flutter_tools/lib/src/commands/run.dart +++ b/packages/flutter_tools/lib/src/commands/run.dart @@ -9,6 +9,7 @@ import 'package:path/path.dart' as path; import '../application_package.dart'; import '../base/common.dart'; +import '../base/utils.dart'; import '../build_configuration.dart'; import '../dart/pub.dart'; import '../device.dart'; @@ -17,7 +18,6 @@ import '../globals.dart'; import '../runner/flutter_command.dart'; import '../toolchain.dart'; import 'apk.dart'; -import 'devices.dart'; import 'install.dart'; /// Given the value of the --target option, return the path of the Dart file diff --git a/packages/flutter_tools/templates/create/android/AndroidManifest.xml.tmpl b/packages/flutter_tools/templates/create/android/AndroidManifest.xml.tmpl index c6455e778cc..3cc48551422 100644 --- a/packages/flutter_tools/templates/create/android/AndroidManifest.xml.tmpl +++ b/packages/flutter_tools/templates/create/android/AndroidManifest.xml.tmpl @@ -1,5 +1,5 @@ diff --git a/packages/flutter_tools/templates/create/ios/Info.plist.tmpl b/packages/flutter_tools/templates/create/ios/Info.plist.tmpl index 8b317f39827..88a6066be8c 100644 --- a/packages/flutter_tools/templates/create/ios/Info.plist.tmpl +++ b/packages/flutter_tools/templates/create/ios/Info.plist.tmpl @@ -7,7 +7,7 @@ CFBundleExecutable Runner CFBundleIdentifier - {{projectIdentifier}} + {{iosIdentifier}} CFBundleInfoDictionaryVersion 6.0 CFBundleName