misc-fred/bin/sassw

70 lines
2.4 KiB
Python
Executable File

#! /usr/bin/python3
#
# Run sassc and watch for changes in source files (using inotitfy) to rebuild
# automatically.
#
# Usage: sassw INPUT
# (output will automatically be INPUT with .scss changed to .css)
import json
import glob
import os
import pyinotify
import subprocess
import sys
import time
filename = sys.argv[1] if len(sys.argv) > 1 else '.'
if os.path.isdir(filename):
scss_filenames = [x for x in os.listdir(filename) if not x.startswith('_') and x.endswith('.scss')]
if not scss_filenames:
print('Error: directory specified but no proper scss file within.', file=sys.stderr)
filenames = [os.path.join(filename, x) for x in scss_filenames]
else:
filenames = sys.argv[1:]
def build():
global sources, directories
directories = set()
sources = set()
for filename in filenames:
result = subprocess.run(
['sassc', '-mauto', filename, filename.replace('.scss', '.css')],
capture_output=True,
text=True)
sys.stdout.write(result.stdout)
sys.stderr.write(result.stderr)
if result.returncode:
# error
with open(filename.replace('.scss', '.css'), 'w') as fd:
print('''body::before {
white-space: pre;
font-family: monospace;
content: "%s";
}''' % result.stderr.replace('\n', '\\A').replace('"', '\\"'),
file=fd)
basepath = os.path.abspath(os.path.dirname(filename))
sources = sources.union(set([os.path.abspath(os.path.join(basepath, x))
for x in json.load(open(filename.replace('.scss', '.css.map')))['sources']]))
directories = directories.union(set([os.path.dirname(x) for x in sources]))
class EventManager(pyinotify.ProcessEvent):
def process_default(self, event):
if event.pathname in sources:
filename = os.path.basename(event.pathname)
print(f'{filename} changed, building', end='')
t0 = time.time()
build()
print(f' ({time.time() - t0:.2f}s)')
print('>>> Building %s' % ' '.join(filenames))
build()
wm = pyinotify.WatchManager()
notifier = pyinotify.Notifier(wm, default_proc_fun=EventManager())
for directory in directories:
wm.add_watch(directory, pyinotify.IN_CLOSE_WRITE)
notifier.coalesce_events()
print('>>> Sassw is watching for changes. Press Ctrl-C to stop.')
notifier.loop()