| /* |
| * grunt-contrib-watch |
| * http://gruntjs.com/ |
| * |
| * Copyright (c) 2018 "Cowboy" Ben Alman, contributors |
| * Licensed under the MIT license. |
| */ |
| |
| 'use strict'; |
| |
| var path = require('path'); |
| var Gaze = require('gaze').Gaze; |
| var _ = require('lodash'); |
| var waiting = 'Waiting...'; |
| var changedFiles = Object.create(null); |
| var watchers = []; |
| |
| module.exports = function(grunt) { |
| |
| var taskrun = require('./lib/taskrunner')(grunt); |
| |
| // Default date format logged |
| var dateFormat = function(time) { |
| grunt.log.writeln(String( |
| 'Completed in ' + |
| time.toFixed(3) + |
| 's at ' + |
| (new Date()).toString() |
| ).cyan + ' - ' + waiting); |
| }; |
| |
| // When task runner has started |
| taskrun.on('start', function() { |
| Object.keys(changedFiles).forEach(function(filepath) { |
| // Log which file has changed, and how. |
| grunt.log.ok('File "' + filepath + '" ' + changedFiles[filepath] + '.'); |
| }); |
| // Reset changedFiles |
| changedFiles = Object.create(null); |
| }); |
| |
| // When task runner has ended |
| taskrun.on('end', function(time) { |
| if (time > 0) { |
| dateFormat(time); |
| } |
| }); |
| |
| // When a task run has been interrupted |
| taskrun.on('interrupt', function() { |
| grunt.log.writeln('').write('Scheduled tasks have been interrupted...'.yellow); |
| }); |
| |
| // When taskrun is reloaded |
| taskrun.on('reload', function() { |
| taskrun.clearRequireCache(Object.keys(changedFiles)); |
| grunt.log.writeln('').writeln('Reloading watch config...'.cyan); |
| }); |
| |
| grunt.registerTask('watch', 'Run predefined tasks whenever watched files change.', function(target) { |
| var self = this; |
| var name = self.name || 'watch'; |
| |
| // Close any previously opened watchers |
| watchers.forEach(function(watcher) { |
| watcher.close(); |
| }); |
| watchers = []; |
| |
| // Never gonna give you up, never gonna let you down |
| if (grunt.config([name, 'options', 'forever']) !== false) { |
| taskrun.forever(); |
| } |
| |
| // If a custom dateFormat function |
| var df = grunt.config([name, 'options', 'dateFormat']); |
| if (typeof df === 'function') { |
| dateFormat = df; |
| } |
| |
| if (taskrun.running === false) { |
| grunt.log.writeln(waiting); |
| } |
| |
| // Initialize taskrun |
| var targets = taskrun.init(name, {target: target}); |
| |
| targets.forEach(function(target) { |
| if (typeof target.files === 'string') { |
| target.files = [target.files]; |
| } |
| |
| // Process into raw patterns |
| var patterns = _.chain(target.files).flatten().map(function(pattern) { |
| return grunt.config.process(pattern); |
| }).value(); |
| |
| // Validate the event option |
| if (typeof target.options.event === 'string') { |
| target.options.event = [target.options.event]; |
| } |
| |
| var eventCwd = process.cwd(); |
| if (target.options.cwd && target.options.cwd.event) { |
| eventCwd = target.options.cwd.event; |
| } |
| |
| // Set cwd if options.cwd.file is set |
| if (typeof target.options.cwd !== 'string' && target.options.cwd.files) { |
| target.options.cwd = target.options.cwd.files; |
| } |
| |
| // Create watcher per target |
| watchers.push(new Gaze(patterns, target.options, function(err) { |
| if (err) { |
| if (typeof err === 'string') { |
| err = new Error(err); |
| } |
| grunt.log.writeln('ERROR'.red); |
| grunt.fatal(err); |
| return taskrun.done(); |
| } |
| |
| // Log all watched files with --verbose set |
| if (grunt.option('verbose')) { |
| var watched = this.watched(); |
| Object.keys(watched).forEach(function(watchedDir) { |
| watched[watchedDir].forEach(function(watchedFile) { |
| grunt.log.writeln('Watching ' + path.relative(process.cwd(), watchedFile) + ' for changes.'); |
| }); |
| }); |
| } |
| |
| // On changed/added/deleted |
| this.on('all', function(status, filepath) { |
| |
| // Skip events not specified |
| if (!_.includes(target.options.event, 'all') && |
| !_.includes(target.options.event, status)) { |
| return; |
| } |
| |
| filepath = path.relative(eventCwd, filepath); |
| |
| // Skip empty filepaths |
| if (filepath === '') { |
| return; |
| } |
| |
| // If Gruntfile.js changed, reload self task |
| if (target.options.reload || /gruntfile\.(js|coffee)/i.test(filepath)) { |
| taskrun.reload = true; |
| } |
| |
| // Emit watch events if anyone is listening |
| if (grunt.event.listeners('watch').length > 0) { |
| grunt.event.emit('watch', status, filepath, target.name); |
| } |
| |
| // Group changed files only for display |
| changedFiles[filepath] = status; |
| |
| // Add changed files to the target |
| if (taskrun.targets[target.name]) { |
| if (!taskrun.targets[target.name].changedFiles) { |
| taskrun.targets[target.name].changedFiles = Object.create(null); |
| } |
| taskrun.targets[target.name].changedFiles[filepath] = status; |
| } |
| |
| // Queue the target |
| if (taskrun.queue.indexOf(target.name) === -1) { |
| taskrun.queue.push(target.name); |
| } |
| |
| // Run the tasks |
| taskrun.run(); |
| }); |
| |
| // On watcher error |
| this.on('error', function(err) { |
| if (typeof err === 'string') { |
| err = new Error(err); |
| } |
| grunt.log.error(err.message); |
| }); |
| })); |
| }); |
| |
| }); |
| }; |