Skip to content

Instantly share code, notes, and snippets.

@gudbergur
Created May 4, 2012 22:07
Show Gist options
  • Save gudbergur/2598032 to your computer and use it in GitHub Desktop.
Save gudbergur/2598032 to your computer and use it in GitHub Desktop.
watchjs - Watch Javascript/CoffeeScript files for changes, concatenate and uglify

watchjs - Watch Javascript/CoffeeScript files for changes, concatenate and uglify

Just a very simple Python script (that depends on Node executables :p) to concatenate JS/Coffeescript files and compress them. I run a Procfile with Foreman that runs this python script on the js/ directory in small projects + stylus on the .styl files. It's similar to some functionality of Brunch.io but where Brunch is not suited I needed a small wrapper to do this for me.

Usage:

chmod +x watchjs.py

./watchjs.py <directory> <output filename>

Few notes: it concatenates files by filename, so it's best to prefix files with order numbers. Files that have the extension ".min.js" are not run through Uglify. You can uncomment lines in the code for Mac OS X, and the computer will announce verbally when there are errors in compilation.

Requirements:

Node's NPM: uglifyjs and coffee need to be in path

Python's PIP: envoy, clint

#!/usr/bin/python
import os, time, sys
from functools import partial
import envoy
from clint.textui import puts, indent
from clint.textui.colored import red, green, cyan
def check_ext(filename, ext):
if type(ext) is not list:
ext = [ext]
return filename.split(".")[-1] in ext
assert len(sys.argv) == 3, "Usage: watchjs <directory> <filename>"
path = sys.argv[1] + "/" if sys.argv[1][-1] != "/" else sys.argv[1]
name = sys.argv[2]
fullname = path+name
times = {}
just_compiled = False
first_loop = True
puts(cyan("Running watchjs"))
while True:
changed = False
files = filter(lambda x:partial(check_ext,ext=["js", "coffee"])(x) and x != name, os.listdir(path))
files.sort()
for f in files:
if first_loop:
puts(green("Watching "+f))
modtime = os.stat(path+f).st_mtime
if times.has_key(f) and times[f] != modtime and not just_compiled:
puts(green("Changed: "+f))
changed = True
elif not times.has_key(f) and not first_loop:
puts(green("Added: "+f))
changed = True
times[f] = modtime
just_compiled = False
if changed or first_loop:
concatted = ""
for f in files:
source = ""
if check_ext(f, "coffee"):
cmd = envoy.run("coffee -p %s" % (path+f,))
if cmd.std_err:
puts(red("Error compiling %s:" % (path+f,)))
with indent(4):
puts(red(cmd.std_err))
#Uncomment for Mac OS X
#envoy.run("say 'o, no!'")
concatted = ""
break
else:
source = cmd.std_out
else:
source = open(path+f, "r").read()
if f[-7:] == ".min.js":
concatted += source
else:
uglified = envoy.run("uglifyjs", data=source)
if uglified.std_err:
puts(red("Error compiling %s:" % (path+f,)))
with indent(4):
puts(red(uglified.std_err))
#Uncomment for Mac OS X
#envoy.run("say 'o, no!'")
concatted = ""
break
else:
concatted += uglified.std_out
if concatted:
output = open(fullname, "w")
output.write(concatted)
output.close()
puts(green("Compiled to "+name))
compiled = True
first_loop = False
time.sleep (1)
@19h
Copy link

19h commented Apr 28, 2013

node-dev it is. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment