Skip to content

Instantly share code, notes, and snippets.

@maniartech
Forked from gudbergur/README.md
Created November 25, 2012 17:22
Show Gist options
  • Save maniartech/4144416 to your computer and use it in GitHub Desktop.
Save maniartech/4144416 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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment