Skip to content

Instantly share code, notes, and snippets.

@JamieMason
Created September 26, 2012 08:16
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save JamieMason/3786735 to your computer and use it in GitHub Desktop.
Save JamieMason/3786735 to your computer and use it in GitHub Desktop.
Watch a folder for changes to files, then reload Chrome
#!/usr/bin/env ruby
require 'tempfile'
require 'fileutils'
# Signals
trap("SIGINT") { exit }
# Setup
TARGET_FOLDER = ARGV[0]
TARGET_URL = ARGV[1]
if TARGET_FOLDER.nil? || TARGET_URL.nil?
puts "Usage: #{$0} TARGET_FOLDER TARGET_URL"
exit
end
# Apple script wrapper class
class AppleScript
def initialize(content)
@file = Tempfile.new('applescript')
@file.write(content)
@file.close
FileUtils.chmod(0755, @file.path)
end
def run(*args)
%x[#{@file.path} #{args.join(" ")}]
end
end
# Watcher wrapper class
class Watcher
EXTENSIONS = %w( htm html css js jpg jpeg gif png php asp rb )
def initialize(path)
@directory = path
@file_list = build_file_list
@callbacks = {}
end
# Register callback to run on file change
def on_change(&block)
@callbacks[:change] = block
end
# Run the watcher event loop
def run!
loop do
new_file_list = build_file_list
unless (diff = @file_list - new_file_list).empty?
@file_list = new_file_list
sleep 0.5
diff.each do |meta|
@callbacks[:change].call(meta[0])
end
end
sleep 0.5
end
end
def build_file_list
list = EXTENSIONS.map do |ext|
Dir[File.join(@directory, "**", "*.#{ext}")]
end
list.flatten!
list.collect do |file|
[file, File.stat(file).mtime.to_i]
end
end
end
script_content = <<-APPLESCRIPT
#!/usr/bin/osascript
on run argv
set theUrl to "about:blank"
if (count of argv) > 0 then
set theUrl to item 1 of argv
if not (theUrl starts with "http://" or theUrl starts with "https://") then
set theUrl to "http://" & theUrl
end if
end if
tell application "Google Chrome"
set found to false
set theWindowIndex to 0
repeat with theWindow in every window
set theTabIndex to 0
repeat with theTab in every tab of theWindow
set theTabIndex to theTabIndex + 1
if theTab's URL starts with theUrl then
set found to true
tell application "Google Chrome" to set active tab index of theWindow to theTabIndex
tell theTab to reload
end if
end repeat
end repeat
if not found then
set URL of (active tab of (make new window)) to theUrl
end if
end tell
end run
APPLESCRIPT
# Run it
script = AppleScript.new(script_content)
watcher = Watcher.new(TARGET_FOLDER)
watcher.on_change do |path|
puts "- #{path} changed."
script.run(TARGET_URL)
end
watcher.run!
@JamieMason
Copy link
Author

  1. Save files to ~/reload-chrome.sh and ~/watch.rb
  2. To run, pass ruby ~/watch.rb path_to_dev_folder url_to_reload, eg: ruby ~/watch.rb ~/Sites/Awesome http://localhost/awesome

@JamieMason
Copy link
Author

Update 5 Dev 2012

Updated with @joshnesbitt's improved fork, ony one Ruby file is needed now - no seperate applescript file.

Installation
Save file to your home directory as eg "watch.rb"

Usage
The script takes absolute or relative paths, so either of the below will work;

ruby ~/watch.rb ~/Sites/Awesome http://localhost/awesome

or

cd ~/Sites/lolwut
ruby ~/watch.rb . http://localhost/lolwut

While the script is running; any time you save a file in eg ~/Sites/lolwut Chrome will reload any tabs open at http://localhost/lolwut.

If you regularly edit files other than htm html css js jpg jpeg gif png php asp rb, just add your file extensions to that list on line 35.

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