Skip to content

Instantly share code, notes, and snippets.

@mashihua
Created July 3, 2012 10:36
Show Gist options
  • Save mashihua/3038966 to your computer and use it in GitHub Desktop.
Save mashihua/3038966 to your computer and use it in GitHub Desktop.
watch file or directory
#!/usr/bin/env coffee
{watch,eventWatch} = require './watch'
{spawn} = require 'child_process'
less = require 'less'
path = require 'path'
watch 'lib', {extention: '.coffee'}, (err, file) ->
throw err if err
coffee = spawn 'coffee', ['-c', '-o', 'lib', "#{file}"]
(item.on 'data',(data) -> console.log "#{data}") for item in [coffee.stdout,coffee.stderr]
eventWatch 'less', {extention: '.less'}, (event) ->
event.on 'error', (error) ->
console.log error
event.on 'deleted', (file) ->
console.log "Deleted less/#{file}"
fs.unlinkSync "./less/#{path.basename file, '.less'}.css"
for item in ['created','modified']
do (item) ->
event.on item, (file) ->
options =
compress: false
yuicompress: false
optimization: 1
silent: false
paths: [path.resolve process.cwd(), "less"]
color: true
strictImports: false
input = fs.readFileSync "less/#{file}", 'utf8'
less.render input, options, (err, css) ->
if err
less.writeError err
else
fd = fs.openSync "./less/#{path.basename file, '.less'}.css", 'w'
fs.writeSync fd, css, 0, 'utf8'
#!/usr/bin/env coffee
###
watch file or directory
By Shihua Ma
Example:
watch = require('watch').watch
watch __filename
watch __dirname, (err, file) -> console.log file
watch __dirname, {extention: '.coffee'}, (err, file) ->
{spawn} = require 'child_process';
coffee = spawn 'coffee', ['-c', '-o', 'lib', 'src']
(item.on 'data',(data) -> console.log data) for item in [coffee.stdout,coffee.stderr]
###
fs = require 'fs'
util = require 'util'
path = require 'path'
events = require 'events'
map = {}
# Watch files in a directory and recursive the sub directory
watchFiles = (dir, files, options, callback) ->
for filename in files when not options.ignore filename
do (filename) ->
# The file or directory
file = "#{dir}/#{filename}"
fs.stat file, (err, stats)->
if err
callback err if err.code isnt 'ENOENT'
else
# Recursive this directory
if stats.isDirectory()
watchDir file, options, callback
# Match the file extention
else if stats.isFile() && file[file.length - options.extention.length..] is options.extention
# Watch this file
fs.watchFile file, (curr, prev) ->
# Delete file event
if curr.nlink is 0
callback null, file, 'delete'
fs.unwatchFile file
return
# Change file event
return if curr.nlink isnt 0 and curr.mtime.getTime() is prev.mtime.getTime()
callback null, file, 'change'
# Watch the directory
watchDir = (dir, options, callback) ->
func = ->
# Reads the contents of a directory.
fs.readdir dir, (err, files) ->
if err
callback err
return
else
#Insert to a map
if not map[dir]
map[dir] = files
else
# New file event
newFiles = files.filter ( item )->
if item not in map[dir] and item[item.length - options.extention.length..] is options.extention
callback null, item, 'create'
item
map[dir] = files
files = newFiles ? []
# Watch this directory
watchFiles dir, files, options, callback
# Watch this directory
fs.watchFile dir, (curr, prev) ->
# Delete directory event
if curr.nlink is 0
callback null, dir, 'delete'
fs.unwatchFile dir
# Rewatch this directory
func() if curr.size > prev.size
func()
# Watch api
exports.watch = (dir_name, options, callback) ->
# Who is not given callback
if not callback
callback ?= options ? ()->
options = {}
# File extention
options.extention ?= ""
# Ignore method
if not options.ignore
options.ignore = (file) ->
return /^\./.test file
# Directory status
fs.stat dir_name, (err, stats) ->
if err
util.error "Error for reading #{dir_name}"
callback err
else
# Watch the directory
if stats.isDirectory()
watchDir dir_name, options, callback
# Watch the file if file given
else if stats.isFile()
watchFiles (path.dirname dir_name), [dir_name], options, callback
# Watch directory or file, the `callback` argument is a function with `EventEmitter` instance.
# The `EventEmitter` have follow event
# * `error` , If `fs` api emits an 'error' event - it will forwarded here
# * `create`, If file or directory was created
# * `change`, If file or directory was changed
# * `delete`, If file or directory was delete
exports.eventWatch = (dir_name, options, callback) ->
em = new events.EventEmitter();
monitor = (err, files, event) ->
if err
em.emit 'error', err
else
em.emit event, files
exports.watch dir_name, options, monitor
callback em
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment