Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

add ide-init to repo

  • Loading branch information...
commit 5678d43353d74cecb44a74ec6a0ee94426f7e14e 1 parent 5fcd7f6
BinChen authored
View
45 Gruntfile.js
@@ -0,0 +1,45 @@
+/*
+ * grunt-init
+ * https://gruntjs.com/
+ *
+ * Copyright (c) 2012 "Cowboy" Ben Alman, contributors
+ * Licensed under the MIT license.
+ */
+
+'use strict';
+
+module.exports = function(grunt) {
+
+ // Project configuration.
+ grunt.initConfig({
+ jshint: {
+ all: [
+ 'Gruntfile.js',
+ 'tasks/*.js'
+ ],
+ options: {
+ jshintrc: '.jshintrc'
+ }
+ },
+
+ // Unit tests.
+ nodeunit: {
+ tests: ['test/*_test.js']
+ }
+ });
+
+ // Actually load this plugin's task(s).
+ grunt.loadTasks('tasks');
+
+ // These plugins provide necessary tasks.
+ grunt.loadNpmTasks('grunt-contrib-jshint');
+ grunt.loadNpmTasks('grunt-contrib-nodeunit');
+
+ // Whenever the "test" task is run, first clean the "tmp" dir, then run this
+ // plugin's task(s), then test the result.
+ grunt.registerTask('test', 'nodeunit');
+
+ // By default, lint and run all tests.
+ grunt.registerTask('default', ['jshint', 'test']);
+
+};
View
22 LICENSE-MIT
@@ -0,0 +1,22 @@
+Copyright (c) 2012 Cocktails IDE, contributors
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
View
6 README.md
@@ -1,4 +1,2 @@
-ide-init
-========
-
-ide initial
+# ide-init
+> Generate project template.
View
33 package.json
@@ -0,0 +1,33 @@
+{
+ "name": "ide-init",
+ "description": "Generate ide template.",
+ "version": "0.1.0",
+ "homepage": "https://github.com/binchen911/ide-init",
+ "author": {
+ "name": "IDE Team"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/binchen911/ide-init.git"
+ },
+ "bugs": {
+ "url": "https://github.com/binchen911/ide-init/issues"
+ },
+ "licenses": [
+ {
+ "type": "MIT",
+ "url": ""
+ }
+ ],
+ "main": "Gruntfile.js",
+ "engines": {
+ "node": ">= 0.6.0"
+ },
+ "scripts": {
+ "test": "grunt test"
+ },
+ "dependencies": {
+ "prompt": "~0.1.12",
+ "semver": "~1.0.14"
+ }
+}
View
499 tasks/init.js
@@ -0,0 +1,499 @@
+/*
+ * grunt-init
+ * https://gruntjs.com/
+ *
+ * Copyright (c) 2012 "Cowboy" Ben Alman, contributors
+ * Licensed under the MIT license.
+ */
+
+'use strict';
+
+module.exports = function (grunt) {
+
+ // Nodejs libs.
+ var path = require('path');
+
+ // External libs.
+ var semver = require('semver');
+
+ // Internal libs.
+ var git = require('./lib/git').init(grunt);
+ var prompt = require('./lib/prompt').init(grunt);
+
+ // ==========================================================================
+ // TASKS
+ // ==========================================================================
+
+ // An array of all available license files.
+ function availableLicenses() {
+ return grunt.task.expandFiles('init/licenses/*').map(function (obj) {
+ return path.basename(String(obj)).replace(/^LICENSE-/, '');
+ });
+ }
+
+ grunt.registerInitTask('create', 'IDE initial template', function () {
+ // Extra arguments will be applied to the template file.
+ var args = grunt.util.toArray(arguments);
+ // Template name.
+ var name = args.shift();
+
+ // Valid init templates (.js or .coffee files).
+ var templates = {};
+ grunt.task.expandFiles('init/*.{js,coffee}').forEach(function (fileobj) {
+ if (__dirname === fileobj.base) {
+ // Add template (plus its path) to the templates object.
+ var basename = path.basename(fileobj.abs).replace(/\.(?:js|coffee)/, '');
+ templates[basename] = require(fileobj.abs);
+ }
+ });
+ var initTemplate = templates[name];
+
+ // Give the user a little help.
+ grunt.log.writelns(
+ 'This task will create one or more files in the current directory, ' +
+ 'based on the environment and the answers to a few questions. ' +
+ 'Note that answering "?" to any question will show question-specific ' +
+ 'help and answering "none" to most questions will leave its value blank.'
+ );
+
+ // Abort if a valid template was not specified.
+ if (!initTemplate) {
+ grunt.log.writeln();
+ if (name) {
+ grunt.log.write('Loading "' + name + '" init template...').error();
+ }
+ grunt.log.writelns('A valid init template name must be specified, eg. ' +
+ '"grunt create:mojito". The currently-available templates are:');
+ Object.keys(templates).forEach(function (name) {
+ var description = templates[name].description || '(no description)';
+ grunt.log.writelns(name.cyan + ' - ' + description);
+ });
+ return !name;
+ }
+
+ // Abort if matching files or directories were found (to avoid accidentally
+ // nuking them).
+ if (initTemplate.warnOn && grunt.file.expand(initTemplate.warnOn).length > 0) {
+ grunt.log.writeln();
+ grunt.warn('Existing files may be overwritten!');
+ }
+
+ // This task is asynchronous.
+ var taskDone = this.async();
+
+ var pathPrefix = 'init/' + name + '/root/';
+
+ // Useful init sub-task-specific utilities.
+ var init = {
+ // Expose prompt interface on init object.
+ process:prompt.process,
+ prompt:prompt.prompt,
+ prompts:prompt.prompts,
+ // Expose any user-specified default init values.
+ defaults:grunt.task.readDefaults('init/defaults.json'),
+ // Expose rename rules for this template.
+ renames:grunt.task.readDefaults('init', name, 'rename.json'),
+ // Return an object containing files to copy with their absolute source path
+ // and relative destination path, renamed (or omitted) according to rules in
+ // rename.json (if it exists).
+ filesToCopy:function (props) {
+ var files = {};
+ // Exclusion patterns.
+ var patterns = Object.keys(init.renames).filter(function (key) {
+ return !init.renames[key];
+ }).map(function (key) {
+ return '!' + pathPrefix + key;
+ });
+ // Inclusion pattern.
+ patterns.push(pathPrefix + '**');
+ // Iterate over all source files.
+ grunt.task.expandFiles({dot:true}, patterns).forEach(function (obj) {
+ // Get the source filepath relative to the template root.
+ var src = obj.rel.slice(pathPrefix.length);
+ // Get the destination filepath.
+ var dest = init.renames[src];
+ // Create a property for this file.
+ files[dest ? grunt.template.process(dest, {data:props, delimiters:'init'}) : src] = obj.rel;
+ });
+ return files;
+ },
+ // Search init template paths for filename.
+ srcpath:function (arg1) {
+ if (arg1 == null) {
+ return null;
+ }
+ var args = ['init', name, 'root'].concat(grunt.util.toArray(arguments));
+ return grunt.task.getFile.apply(grunt.file, args);
+ },
+ // Determine absolute destination file path.
+ destpath:path.join.bind(path, process.cwd()),
+ // Given some number of licenses, add properly-named license files to the
+ // files object.
+ addLicenseFiles:function (files, licenses) {
+ licenses.forEach(function (license) {
+ var fileobj = grunt.task.expandFiles('init/licenses/LICENSE-' + license)[0];
+ files['LICENSE-' + license] = fileobj ? fileobj.rel : null;
+ });
+ },
+ // Given an absolute or relative source path, and an optional relative
+ // destination path, copy a file, optionally processing it through the
+ // passed callback.
+ copy:function (srcpath, destpath, options) {
+ // Destpath is optional.
+ if (typeof destpath !== 'string') {
+ options = destpath;
+ destpath = srcpath;
+ }
+ // Ensure srcpath is absolute.
+ if (!grunt.file.isPathAbsolute(srcpath)) {
+ srcpath = init.srcpath(srcpath);
+ }
+ // Use placeholder file if no src exists.
+ if (!srcpath) {
+ srcpath = grunt.task.getFile('init/misc/placeholder');
+ }
+ grunt.verbose.or.write('Writing ' + destpath + '...');
+ try {
+ grunt.file.copy(srcpath, init.destpath(destpath), options);
+ grunt.verbose.or.ok();
+ } catch (e) {
+ grunt.verbose.or.error().error(e);
+ throw e;
+ }
+ },
+ // Iterate over all files in the passed object, copying the source file to
+ // the destination, processing the contents.
+ copyAndProcess:function (files, props, options) {
+ options = grunt.util._.defaults(options || {}, {
+ process:function (contents) {
+ return grunt.template.process(contents, {data:props, delimiters:'init'});
+ }
+ });
+ Object.keys(files).forEach(function (destpath) {
+ var o = Object.create(options);
+ var srcpath = files[destpath];
+ // If srcpath is relative, match it against options.noProcess if
+ // necessary, then make srcpath absolute.
+ var relpath;
+ if (srcpath && !grunt.file.isPathAbsolute(srcpath)) {
+ if (o.noProcess) {
+ relpath = srcpath.slice(pathPrefix.length);
+ o.noProcess = grunt.file.isMatch({matchBase:true}, o.noProcess, relpath);
+ }
+ srcpath = grunt.task.getFile(srcpath);
+ }
+ // Copy!
+ init.copy(srcpath, destpath, o);
+ });
+ },
+ // Save a package.json file in the destination directory. The callback
+ // can be used to post-process properties to add/remove/whatever.
+ writePackageJSON:function (filename, props, callback) {
+ var pkg = {};
+ // Basic values.
+ ['name', 'title', 'description', 'version', 'homepage'].forEach(function (prop) {
+ if (prop in props) {
+ pkg[prop] = props[prop];
+ }
+ });
+ // Author.
+ var hasAuthor = Object.keys(props).some(function (prop) {
+ return (/^author_/).test(prop);
+ });
+ if (hasAuthor) {
+ pkg.author = {};
+ ['name', 'email', 'url'].forEach(function (prop) {
+ if (props['author_' + prop]) {
+ pkg.author[prop] = props['author_' + prop];
+ }
+ });
+ }
+ // Other stuff.
+ if ('repository' in props) {
+ pkg.repository = {type:'git', url:props.repository};
+ }
+ if ('bugs' in props) {
+ pkg.bugs = {url:props.bugs};
+ }
+ if (props.licenses) {
+ pkg.licenses = props.licenses.map(function (license) {
+ return {type:license, url:props.homepage + '/blob/master/LICENSE-' + license};
+ });
+ }
+
+ // Node/npm-specific (?)
+ if (props.main) {
+ pkg.main = props.main;
+ }
+ if (props.bin) {
+ pkg.bin = props.bin;
+ }
+ if (props.node_version) {
+ pkg.engines = {node:props.node_version};
+ }
+ if (props.npm_test) {
+ pkg.scripts = {test:props.npm_test};
+ if (props.npm_test.split(' ')[0] === 'grunt') {
+ if (!props.devDependencies) {
+ props.devDependencies = {};
+ }
+ props.devDependencies.grunt = '~' + grunt.version;
+ }
+ }
+
+ if (props.dependencies) {
+ pkg.dependencies = props.dependencies;
+ }
+ if (props.devDependencies) {
+ pkg.devDependencies = props.devDependencies;
+ }
+ if (props.keywords) {
+ pkg.keywords = props.keywords;
+ }
+
+ // Allow final tweaks to the pkg object.
+ if (callback) {
+ pkg = callback(pkg, props);
+ }
+
+ // Write file.
+ grunt.verbose.or.write('Writing ' + filename + '...');
+ try {
+ grunt.file.write(init.destpath(filename), JSON.stringify(pkg, null, 2));
+ grunt.verbose.or.ok();
+ } catch (e) {
+ grunt.verbose.or.error().error(e);
+ throw e;
+ }
+ }
+ };
+
+ // Make args available as flags.
+ init.flags = {};
+ args.forEach(function (flag) {
+ init.flags[flag] = true;
+ });
+
+ // Show any template-specific notes.
+ if (initTemplate.notes) {
+ grunt.log.subhead('"' + name + '" template notes:').writelns(initTemplate.notes);
+ }
+
+ // Execute template code, passing in the init object, done function, and any
+ // other arguments specified after the init:name:???.
+ initTemplate.template.apply(this, [grunt, init, function () {
+ // Fail task if errors were logged.
+ if (grunt.task.current.errorCount) {
+ taskDone(false);
+ }
+ // Otherwise, print a success message.
+ grunt.log.writeln().writeln('Initialized from template "' + name + '".');
+ // All done!
+ taskDone();
+ }].concat(args));
+ }
+ )
+ ;
+
+// Built-in prompt options.
+// These generally follow the node "prompt" module convention, except:
+// * The "default" value can be a function which is executed at run-time.
+// * An optional "sanitize" function has been added to post-process data.
+ grunt.util._.extend(prompt.prompts, {
+ name:{
+ message:'Project name',
+ default:function (value, data, done) {
+ var types = ['javascript', 'js'];
+ if (data.type) {
+ types.push(data.type);
+ }
+ var type = '(?:' + types.join('|') + ')';
+ // This regexp matches:
+ // leading type- type. type_
+ // trailing -type .type _type and/or -js .js _js
+ var re = new RegExp('^' + type + '[\\-\\._]?|(?:[\\-\\._]?' + type + ')?(?:[\\-\\._]?js)?$', 'ig');
+ // Strip the above stuff from the current dirname.
+ var name = path.basename(process.cwd()).replace(re, '');
+ // Remove anything not a letter, number, dash, dot or underscore.
+ name = name.replace(/[^\w\-\.]/g, '');
+ done(null, name);
+ },
+ validator:/^[\w\-\.]+$/,
+ warning:'Must be only letters, numbers, dashes, dots or underscores.',
+ sanitize:function (value, data, done) {
+ // An additional value, safe to use as a JavaScript identifier.
+ data.js_safe_name = value.replace(/[\W_]+/g, '_').replace(/^(\d)/, '_$1');
+ // An additional value that won't conflict with NodeUnit unit tests.
+ data.js_test_safe_name = data.js_safe_name === 'test' ? 'myTest' : data.js_safe_name;
+ // If no value is passed to `done`, the original property isn't modified.
+ done();
+ }
+ },
+ title:{
+ message:'Project title',
+ default:function (value, data, done) {
+ var title = data.name || '';
+ title = title.replace(/[\W_]+/g, ' ');
+ title = title.replace(/\w+/g, function (word) {
+ return word[0].toUpperCase() + word.slice(1).toLowerCase();
+ });
+ done(null, title);
+ },
+ warning:'May consist of any characters.'
+ },
+ description:{
+ message:'Description',
+ default:'The best project ever.',
+ warning:'May consist of any characters.'
+ },
+ version:{
+ message:'Version',
+ default:function (value, data, done) {
+ // Get a valid semver tag from `git describe --tags` if possible.
+ grunt.util.spawn({
+ cmd:'git',
+ args:['describe', '--tags'],
+ fallback:''
+ }, function (err, result) {
+ result = String(result).split('-')[0];
+ done(null, semver.valid(result) || '0.1.0');
+ });
+ },
+ validator:semver.valid,
+ warning:'Must be a valid semantic version (semver.org).'
+ },
+ repository:{
+ message:'Project git repository',
+ default:function (value, data, done) {
+ // Change any git@...:... uri to git://.../... format.
+ git.origin(function (err, result) {
+ if (err) {
+ // Attempt to guess at the repo name. Maybe we'll get lucky!
+ result = 'git://github.com/' + (process.env.USER || process.env.USERNAME || '???') + '/' +
+ path.basename(process.cwd()) + '.git';
+ } else {
+ result = result.replace(/^git@([^:]+):/, 'git://$1/');
+ }
+ done(null, result);
+ });
+ },
+ sanitize:function (value, data, done) {
+ // An additional computed "git_user" property.
+ var repo = git.githubUrl(data.repository);
+ var parts;
+ if (repo != null) {
+ parts = repo.split('/');
+ data.git_user = parts[parts.length - 2];
+ data.git_repo = parts[parts.length - 1];
+ done();
+ } else {
+ // Attempt to pull the data from the user's git config.
+ grunt.util.spawn({
+ cmd:'git',
+ args:['config', '--get', 'github.user'],
+ fallback:''
+ }, function (err, result) {
+ data.git_user = String(result) || process.env.USER || process.env.USERNAME || '???';
+ data.git_repo = path.basename(process.cwd());
+ done();
+ });
+ }
+ },
+ warning:'Should be a public git:// URI.'
+ },
+ homepage:{
+ message:'Project homepage',
+ // If GitHub is the origin, the (potential) homepage is easy to figure out.
+ default:function (value, data, done) {
+ done(null, git.githubUrl(data.repository) || 'none');
+ },
+ warning:'Should be a public URL.'
+ },
+ bugs:{
+ message:'Project issues tracker',
+ // If GitHub is the origin, the issues tracker is easy to figure out.
+ default:function (value, data, done) {
+ done(null, git.githubUrl(data.repository, 'issues') || 'none');
+ },
+ warning:'Should be a public URL.'
+ },
+ licenses:{
+ message:'Licenses',
+ default:'MIT',
+ validator:/^[\w\-\.\d]+(?:\s+[\w\-\.\d]+)*$/,
+ warning:'Must be zero or more space-separated licenses. Built-in ' +
+ 'licenses are: ' + availableLicenses().join(' ') + ', but you may ' +
+ 'specify any number of custom licenses.',
+ // Split the string on spaces.
+ sanitize:function (value, data, done) {
+ done(value.split(/\s+/));
+ }
+ },
+ author_name:{
+ message:'Author name',
+ default:function (value, data, done) {
+ // Attempt to pull the data from the user's git config.
+ grunt.util.spawn({
+ cmd:'git',
+ args:['config', '--get', 'user.name'],
+ fallback:'none'
+ }, done);
+ },
+ warning:'May consist of any characters.'
+ },
+ author_email:{
+ message:'Author email',
+ default:function (value, data, done) {
+ // Attempt to pull the data from the user's git config.
+ grunt.util.spawn({
+ cmd:'git',
+ args:['config', '--get', 'user.email'],
+ fallback:'none'
+ }, done);
+ },
+ warning:'Should be a valid email address.'
+ },
+ author_url:{
+ message:'Author url',
+ default:'none',
+ warning:'Should be a public URL.'
+ },
+ jquery_version:{
+ message:'Required jQuery version',
+ default:'*',
+ warning:'Must be a valid semantic version range descriptor.'
+ },
+ node_version:{
+ message:'What versions of node does it run on?',
+ // TODO: pull from grunt's package.json
+ default:'>= 0.6.0',
+ warning:'Must be a valid semantic version range descriptor.'
+ },
+ main:{
+ message:'Main module/entry point',
+ default:function (value, data, done) {
+ done(null, 'lib/' + data.name);
+ },
+ warning:'Must be a path relative to the project root.'
+ },
+ bin:{
+ message:'CLI script',
+ default:function (value, data, done) {
+ done(null, 'bin/' + data.name);
+ },
+ warning:'Must be a path relative to the project root.'
+ },
+ npm_test:{
+ message:'Npm test command',
+ default:'grunt',
+ warning:'Must be an executable command.'
+ },
+ grunt_version:{
+ message:'What versions of grunt does it require?',
+ default:'~' + grunt.version,
+ warning:'Must be a valid semantic version range descriptor.'
+ }
+ });
+
+}
+;
View
82 tasks/init/mojito.js
@@ -0,0 +1,82 @@
+/*
+ * grunt-init
+ * https://gruntjs.com/
+ *
+ * Copyright (c) 2012 "Cowboy" Ben Alman, contributors
+ * Licensed under the MIT license.
+ */
+var join = require('path').join;
+var child_process = require('child_process');
+'use strict';
+
+// Basic template description.
+exports.description = 'Create mojito project.';
+
+// Template-specific notes to be displayed before question prompts.
+exports.notes = 'This template tries to guess file and directory paths, ' +
+ 'but you will most likely need to edit the generated Gruntfile.js file before running grunt. '.red +
+ '_If you run grunt after generating the Gruntfile, and ' +
+ 'it exits with errors, edit the file!_';
+
+// Any existing file or directory matching this wildcard will cause a warning.
+exports.warnOn = '';
+
+// The actual init template.
+exports.template = function (grunt, init, done) {
+
+ init.process({}, [
+ // Prompt for these values.
+ {
+ name:'app_name',
+ message:'your app name?',
+ default:'mojito_demo',
+ warning:''
+ },
+ {
+ name:'type',
+ message:'"app", "mojit", or "custom".?',
+ default:'app',
+ warning:''
+ },
+ {
+ name:'archetype',
+ message:'optional template. Possible values are default, full, simple' +
+ '"app" types also have a "hybrid" archetype which creates an app and a' +
+ 'mojit with common configurations for use with hybrid app. ' +
+ 'If the type is "custom" then this is the path to your own archetype' +
+ 'directory.?',
+ default:'hybrid',
+ warning:''
+ }
+ ], function (err, props) {
+
+ child_process.exec(grunt.runtime.getMojito() + " create " + props.type + " " + props.archetype + " " + props.app_name, function (err, stdout, stderr) {
+ if (err) {
+ grunt.log.error(stderr);
+ } else {
+ grunt.log.success(stdout);
+ // Files to copy (and process).
+ var files = init.filesToCopy(props);
+ Object.prototype.renameProperty = function (oldName, newName) {
+ // Check for the old property name to avoid a ReferenceError in strict mode.
+ if (this.hasOwnProperty(oldName)) {
+ this[newName] = this[oldName];
+ delete this[oldName];
+ }
+ return this;
+ };
+ for (var key in files) {
+ files.renameProperty(key, join(props.app_name, key));
+ }
+ // Actually copy (and process) files.
+ init.copyAndProcess(files, props);
+
+ // All done!
+ done();
+ }
+ });
+
+//
+ });
+
+};
View
70 tasks/init/mojito/root/Gruntfile.js
@@ -0,0 +1,70 @@
+module.exports = function (grunt) {
+ 'use strict';
+
+ // Grunt configuration:
+
+ grunt.initConfig({
+
+ // Project configuration
+ // ---------------------
+ // specify mojito configuration
+
+ mojito:{
+ context:'build:debug'
+ //release flow if version and snapshotTag is setted
+ //version:'1.0.0',
+ //snapshotTag:'tag'
+ },
+ //Specify for remote debugger. Instrument file list and settings.
+ debug:{
+ serverHost:'localhost',
+ serverPort:8080,
+ wserverPort:8080,
+ fileServerPort:8050
+ },
+ //specify pakcages to be add to maitai repository, for multi-pakcage used. Reserved.
+ push:{
+ packages:[]
+ },
+ //specify arguments for rt
+ rt:{
+ iconfile:'',
+ devorship:'dev',
+ simordev:'simulator'//determin the localhost or internet IP
+
+ //host:'', //maitail server host
+ //port:'', //maitail server port
+ //initialtime:'', //RT initial waiting time
+ //frequency:'' //RT query maitai frequency.
+ },
+
+ package:{
+ iossdk:'iphonesimulator6.0',
+
+ apilevel:14
+ },
+ launch:{
+ //ios
+ devicefamily:'iphone', //launch simulator type
+ //android. Will remove after setting up avd manager
+ avdport:5554,
+ device:'avd'
+ },
+ //For screwdriver. Reserved.
+ ci:{
+ svn:'',
+ branch:''
+ },
+ //For manhattan. Reserved.
+ deploy:{
+ appfolder:[],
+ instancename:''
+ }
+
+ });
+
+ // Alias the `default` task to run `build:ios` task instead
+ // User can manual schedule task
+ grunt.registerTask('default', 'build:ios');
+
+};
View
46 tasks/lib/git.js
@@ -0,0 +1,46 @@
+/*
+ * grunt-init
+ * https://gruntjs.com/
+ *
+ * Copyright (c) 2012 "Cowboy" Ben Alman, contributors
+ * Licensed under the MIT license.
+ */
+
+'use strict';
+
+exports.init = function(grunt) {
+ var exports = {};
+
+ // Get the git origin url from the current repo (if possible).
+ exports.origin = function(done) {
+ grunt.util.spawn({
+ cmd: 'git',
+ args: ['remote', '-v']
+ }, function(err, result) {
+ var re = /^origin\s/;
+ var lines;
+ if (!err) {
+ lines = String(result).split('\n').filter(re.test, re);
+ if (lines.length > 0) {
+ done(null, lines[0].split(/\s/)[1]);
+ return;
+ }
+ }
+ done(true, 'none');
+ });
+ };
+
+ // Generate a GitHub web URL from a GitHub repo URI.
+ var githubUrlRegex = /^.+(?:@|:\/\/)(github.com)[:\/](.+?)(?:\.git|\/)?$/;
+ exports.githubUrl = function(uri, suffix) {
+ var matches = githubUrlRegex.exec(uri);
+ if (!matches) { return null; }
+ var url = 'https://' + matches[1] + '/' + matches[2];
+ if (suffix) {
+ url += '/' + suffix.replace(/^\//, '');
+ }
+ return url;
+ };
+
+ return exports;
+};
View
156 tasks/lib/prompt.js
@@ -0,0 +1,156 @@
+/*
+ * grunt-init
+ * https://gruntjs.com/
+ *
+ * Copyright (c) 2012 "Cowboy" Ben Alman, contributors
+ * Licensed under the MIT license.
+ */
+
+'use strict';
+
+// External lib.
+var prompt = require('prompt');
+prompt.message = '[' + '?'.green + ']';
+prompt.delimiter = ' ';
+
+exports.init = function(grunt) {
+ var exports = {};
+
+ // Expose prompts object so that prompts can be added or modified.
+ exports.prompts = {};
+
+ // Prompt user to override default values passed in obj.
+ exports.process = function(defaults, options, done) {
+ // If defaults are omitted, shuffle arguments a bit.
+ if (grunt.util.kindOf(defaults) === 'array') {
+ done = options;
+ options = defaults;
+ defaults = {};
+ }
+
+ // Keep track of any "sanitize" functions for later use.
+ var sanitize = {};
+ options.forEach(function(option) {
+ if (option.sanitize) {
+ sanitize[option.name] = option.sanitize;
+ }
+ });
+
+ // Add one final "are you sure?" prompt.
+ if (options.length > 0) {
+ options.push({
+ message: 'Do you need to make any changes to the above before continuing?'.green,
+ name: 'ANSWERS_VALID',
+ default: 'y/N'
+ });
+ }
+
+ // Ask user for input. This is in an IIFE because it has to execute at least
+ // once, and might be repeated.
+ (function ask() {
+ grunt.log.subhead('Please answer the following:');
+ var result = grunt.util._.clone(defaults);
+ // Loop over each prompt option.
+ grunt.util.async.forEachSeries(options, function(option, done) {
+ var defaultValue;
+ grunt.util.async.forEachSeries(['default', 'altDefault'], function(prop, next) {
+ if (typeof option[prop] === 'function') {
+ // If the value is a function, execute that function, using the
+ // value passed into the return callback as the new default value.
+ option[prop](defaultValue, result, function(err, value) {
+ defaultValue = String(value);
+ next();
+ });
+ } else {
+ // Otherwise, if the value actually exists, use it.
+ if (prop in option) {
+ defaultValue = option[prop];
+ }
+ next();
+ }
+ }, function() {
+ // Handle errors (there should never be errors).
+ option.default = defaultValue;
+ delete option.altDefault;
+ // Wrap validator so that answering '?' always fails.
+ var validator = option.validator;
+ option.validator = function(line, next) {
+ if (line === '?') {
+ return next(false);
+ } else if (validator) {
+ if (validator.test) {
+ return next(validator.test(line));
+ } else if (typeof validator === 'function') {
+ return validator.length < 2 ? next(validator(line)) : validator(line, next);
+ }
+ }
+ next(true);
+ };
+ // Actually get user input.
+ prompt.start();
+ prompt.getInput(option, function(err, line) {
+ if (err) { return done(err); }
+ option.validator = validator;
+ result[option.name] = line;
+ done();
+ });
+ });
+ }, function() {
+ // After all prompt questions have been answered...
+ if (/n/i.test(result.ANSWERS_VALID)) {
+ // User accepted all answers. Suspend prompt.
+ prompt.pause();
+ // Clean up.
+ delete result.ANSWERS_VALID;
+ // Iterate over all results.
+ grunt.util.async.forEachSeries(Object.keys(result), function(name, next) {
+ // If this value needs to be sanitized, process it now.
+ if (sanitize[name]) {
+ sanitize[name](result[name], result, function(err, value) {
+ if (err) {
+ result[name] = err;
+ } else if (arguments.length === 2) {
+ result[name] = value === 'none' ? '' : value;
+ }
+ next();
+ });
+ } else {
+ if (result[name] === 'none') { result[name] = ''; }
+ next();
+ }
+ }, function(err) {
+ // Done!
+ grunt.log.writeln();
+ done(err, result);
+ });
+ } else {
+ // Otherwise update the default value for each user prompt option...
+ options.slice(0, -1).forEach(function(option) {
+ option.default = result[option.name];
+ });
+ // ...and start over again.
+ ask();
+ }
+ });
+ }());
+ };
+
+ // Commonly-used prompt options with meaningful default values.
+ exports.prompt = function(name, altDefault) {
+ // Clone the option so the original options object doesn't get modified.
+ var option = grunt.util._.clone(exports.prompts[name]);
+ option.name = name;
+
+ var defaults = grunt.task.readDefaults('init/defaults.json');
+ if (name in defaults) {
+ // A user default was specified for this option, so use its value.
+ option.default = defaults[name];
+ } else if (arguments.length === 2) {
+ // An alternate default was specified, so use it.
+ option.altDefault = altDefault;
+ }
+ return option;
+ };
+
+ return exports;
+};
Please sign in to comment.
Something went wrong with that request. Please try again.