Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pattern for 'mydir' #16

Closed
artem-malko opened this issue Jul 17, 2014 · 13 comments
Closed

pattern for 'mydir' #16

artem-malko opened this issue Jul 17, 2014 · 13 comments

Comments

@artem-malko
Copy link

Hi. Is there any possibility to write something like that:

watch('myDir/*/', filter(/\.js$/, function(filename) {
    // 
}));

It means that i've got many folders in myDir and i want to watch for js-files in them. Can i use a pattern in myDir value?

@yuanchuan
Copy link
Owner

Did you mean something like this:

watch('myDir/**/*.js',  function(filename) { 

});

That's possible, even without any changes to the node-watch itself.

Pseudo code;

function watchByPattern(pattern, options, callback) {

   // Parsing the pattern into two parts: 
   //   1. directory or filename.
   //   2. the wildcard used for filtering.  
   //
   //  For example:
   //
   //  Given the pattern "myDir/**/*.js",  will return 
   //  the directory 'myDir' and the wildcard "**/*.js".
   var segment = patternParser(pattern);


   // Filter by wildcard, using package "minimatch".
   var filterByWildCard = function(wildcard, callback) {
     return function(filename) {
       if (minimatch(filename, wildcard)) {
         callback(filename);
       }
     }
   }

   watch(
     segment.dir,
     options, 
     filterByWildCard(segment.wildcard, callback)
   );

}

@artem-malko
Copy link
Author

Thanks.
But i've got some problems with this code.

First of all, there can i do my own actions?

I've got this code

function watchByPattern(options, callback) {

   // Filter by wildcard, using package "minimatch".
   var filterByWildCard = function(wildcard, callback) {
     return function(filename) {
       if (minimatch(filename, wildcard)) {
         // callback(filename);
       }
     }
   }

   watch(
        './markup',
        options,
        filterByWildCard('**/**/*.scss', callback),

        function() {
            gulp.start('scss');
        }
   );

}

watchByPattern();

Is it correct? It doesn't work( Could you help me?

@yuanchuan
Copy link
Owner

Missing the minimatch module.

Well, there is the full example:

var minimatch = require('minimatch');
var watch = require('node-watch');

function watchByPattern(pattern, callback) {
  var filterByWildCard = function(wildcard, fn) {
    return function(filename) {
      if (minimatch(filename, wildcard)) {
        fn(filename);
      }
    }
  }
  watch(
    './markup',
    filterByWildCard(pattern, callback)
  );
}

watchByPattern('**/*.scss', function(filename) {
  console.log(filename);
});

@artem-malko
Copy link
Author

Thanks a lot)

@artem-malko
Copy link
Author

Excuse me, there is another problem. If i need to watch for js files too, i have to write something like that:

watchByPattern('**/*.scss', function(filename) {
    console.log(filename);
});

watchByPattern('**/*.js', function(filename) {
    console.log(filename);
});

So, the second watchByPattern doesn't work. Just no events are hired. Only the first works.

Env: Mac, OS X 10.9.4 Node.JS Version 0.10.26

@yuanchuan
Copy link
Owner

Sorry, it's a bug on re-watching a directory.

Try this:

var minimatch = require('minimatch');
var watch = require('node-watch');

var watchByPattern = (function() {
  var patterns = [];
  var ready = true;
  return function(pattern, callback) {
    patterns.push({
      wildcard: pattern,
      callback: callback
    });
    if (ready) {
      ready = false;
      watch('./markup', function(filename) {
        patterns.forEach(function(pat) {
          if (minimatch(filename, pat.wildcard)) {
            pat.callback(filename);
          }
        });
      });
    }
  }
}());


watchByPattern('**/*.scss', function(filename) {
  console.log(filename);
});

watchByPattern('**/*.js', function(filename) {
  console.log(filename);
});

@artem-malko
Copy link
Author

You are really great man) Thanks.
But there is one more question, please. I need to watch not only markup directory, so i write with:

var watchByPattern = (function() {
  var patterns = [];
  var ready = true;
  return function(dir, pattern, callback) {
    patterns.push({
      wildcard: pattern,
      callback: callback
    });
    if (ready) {
      ready = false;
      watch(dir, function(filename) {
        patterns.forEach(function(pat) {
          if (minimatch(filename, pat.wildcard)) {
            pat.callback(filename);
          }
        });
      });
    }
  }
}());

But it doesn't work, if i do with:

watchByPattern('./markup', '**/*.scss', function(filename) {
  console.log(filename);
});

watchByPattern('./images', '*.png', function(filename) {
  console.log(filename);
});

if dirs are similar — everything is ok, but when they are different — no events are hired.
There is a solution — different watchByPattern functions for each dir, but i think, that it can be done more easy) Could you help me?

@yuanchuan
Copy link
Owner

OK.

var minimatch = require('minimatch');
var watch = require('node-watch');

var watchByPattern = (function() {
  var parsePattern = function(input) {
    var current = './';
    var segments = input.split(/\*/);
    return {
      dir: (/^\*/.test(input) ? current : (segments[0] || current)),
      pat: ('*' + segments.slice(1).join('*'))
    }
  }
  var watchStack = {}
  return function(pattern, fn) {
    var input = parsePattern(pattern);
    var stack = { pat: input.pat, callback: fn };
    if (watchStack[input.dir]) {
      watchStack[input.dir].push(stack);
    } else {
      watchStack[input.dir] = [stack];
      watch(input.dir, function(filename) {
        watchStack[input.dir].forEach(function(stack) {
          if (minimatch(filename, stack.pat)) {
            stack.callback(filename);
          }
        });
      });
    };
  }
}());

Usage:

watchByPattern('./markup/**/*.js', function(name) {
  //
});

watchByPattern('**/*.js', function(name) {
  //
});

@yuanchuan
Copy link
Owner

@artem-malko

This code is quite basic, as you can see there is even no options passed inside, and the parsePattern function, which I mentioned early, has not been fully tested.

Anyway, hope this inspired you a bit.

@artem-malko
Copy link
Author

Thank you very much) You're only one made working watcher, which can watch for new and deleted files correctly.
I'll watch for your project)

@artem-malko
Copy link
Author

Hi. I've just improved your lats code. There are you can processing unwatch path. It could be a single string of an array of strings. May be it can be usefull for somebody)

var     minimatch = require('minimatch'),           // Service module for node-watch
        watch = require('node-watch');              // Watcher

// Watcher by node-watch
var watchByPattern = (function() {

    var watchStack = {};

    var parsePattern = function(input, filter) {
        var current = './',
            filterSegment = '',
            segments = input.split(/\*/),
            dir = '',
            pat = '',
            filterPattern = '';

            if (/^\*/.test(input)) {
                dir = current
            } else {
                dir = segments[0] || current;
            }

            pat = '*' + segments.slice(1).join('*');

            filterPattern = filter || false;

            if (filterPattern) {

                if (filterPattern instanceof Array) {

                    for (var i = 0; i < filterPattern.length; i++ ) {
                        filterSegment = filterPattern[i].split(/\*/);
                        filterPattern[i] = '*' + filterSegment.slice(1).join('*');
                    }
                } else {
                    filterSegment = filter.split(/\*/);
                    filterPattern = '*' + filterSegment.slice(1).join('*');
                }
            }

        return {
            dir: dir,
            pat: pat,
            filter: filterPattern
        }
    };

    var patternProcessing = function(pattern, filter, fn) {

        var input = parsePattern(pattern, filter),
            stack = { pat: input.pat, callback: fn, filter: input.filter };

        if (watchStack[input.dir]) {
            watchStack[input.dir].push(stack);
        } else {
            watchStack[input.dir] = [stack];
            watch(input.dir, function(filename) {
                watchStack[input.dir].forEach(function(stack) {
                    var useFilter = false;
                    if (minimatch(filename, stack.pat)) {

                        if (stack.filter) {
                            if (stack.filter instanceof Array) {
                                stack.filter.forEach(function(filterItem) {
                                    if (minimatch(filename, filterItem)) {
                                        useFilter = true;
                                    }
                                });

                                if (useFilter) {
                                    return;
                                } else {
                                    stack.callback(filename);
                                }
                            } else {
                                if (minimatch(filename, stack.filter)) {
                                    return;
                                } else {
                                    stack.callback(filename);   
                                }
                            }

                        } else {
                            stack.callback(filename);
                        }
                    }
                });
            });
        }
    };

    return function(pattern, filter, fn) {

        if (pattern instanceof Array) {
            pattern.forEach(function(patternItem) {
                patternProcessing(patternItem, filter, fn);
            });
        } else {
            patternProcessing(pattern, filter, fn);
        } 
    }
}());

module.exports = watchByPattern;

And the simple watcher code with unwatch path (watchByPattern is a requre of watchByPattern):

    watchByPattern('./markup/modules/**/*.js', './markup/modules/**/moduleData.js', function() {
        gulp.start('concat-plugins-libs-and-modules-lint-modules-js');
    });

@yuanchuan
Copy link
Owner

The indention looks not graceful :D

@artem-malko
Copy link
Author

Yeah, i need mooore indetions)
But what do you think about code?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants