visionmedia-bind 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+
2
+ === 0.0.1 / 2009-03-03
3
+
4
+ * Initial release
@@ -0,0 +1,23 @@
1
+ bin/bind
2
+ bind.gemspec
3
+ examples/demo.html
4
+ examples/log_changes.rb
5
+ examples/refresh_browsers.rb
6
+ examples/style.css
7
+ History.rdoc
8
+ lib/bind/actions/refresh_browsers.rb
9
+ lib/bind/actions.rb
10
+ lib/bind/command_helpers.rb
11
+ lib/bind/listener.rb
12
+ lib/bind/version.rb
13
+ lib/bind.rb
14
+ Manifest
15
+ Rakefile
16
+ README.rdoc
17
+ spec/bind_listener_spec.rb
18
+ spec/fixtures/style.css
19
+ spec/spec_helper.rb
20
+ tasks/docs.rake
21
+ tasks/gemspec.rake
22
+ tasks/spec.rake
23
+ Todo.rdoc
@@ -0,0 +1,36 @@
1
+
2
+ = Bind
3
+
4
+ Bind actions to various file system events, helping aid in
5
+ automation of tasks such as refreshing browser(s) when you
6
+ update a css / sass / js file.
7
+
8
+ == Features
9
+
10
+ * Coming soon
11
+
12
+ == License:
13
+
14
+ (The MIT License)
15
+
16
+ Copyright (c) 2009 TJ Holowaychuk <tj@vision-media.ca>
17
+
18
+ Permission is hereby granted, free of charge, to any person obtaining
19
+ a copy of this software and associated documentation files (the
20
+ 'Software'), to deal in the Software without restriction, including
21
+ without limitation the rights to use, copy, modify, merge, publish,
22
+ distribute, sublicense, an d/or sell copies of the Software, and to
23
+ permit persons to whom the Software is furnished to do so, subject to
24
+ the following conditions:
25
+
26
+ The above copyright notice and this permission notice shall be
27
+ included in all copies or substantial portions of the Software.
28
+
29
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
30
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
32
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
33
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
34
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
35
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36
+ GS IN THE SOFTWARE.
@@ -0,0 +1,16 @@
1
+
2
+ require 'rubygems'
3
+ require 'rake'
4
+ require 'echoe'
5
+ require './lib/bind.rb'
6
+
7
+ Echoe.new("bind", Bind::VERSION::STRING) do |p|
8
+ p.author = "TJ Holowaychuk"
9
+ p.email = "tj@vision-media.ca"
10
+ p.summary = "bind actions to filesystem events"
11
+ p.url = "http://github.com/visionmedia/bind"
12
+ p.runtime_dependencies = []
13
+ p.runtime_dependencies << 'visionmedia-commander >=2.4.6'
14
+ end
15
+
16
+ Dir['tasks/**/*.rake'].sort.each { |lib| load lib }
@@ -0,0 +1,13 @@
1
+
2
+ == Major:
3
+
4
+ * Add support for an eval BEFORE actions, such as building SASS / HAML
5
+
6
+ == Minor:
7
+
8
+ * Support action / event pairs, n to n, not 1 to 1
9
+ * Add more actions / events like atime
10
+
11
+ == Brainstorming:
12
+
13
+ * Nothing
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'bind'
5
+ require 'bind/command_helpers'
6
+ require 'commander'
7
+
8
+ program :name, 'Bind'
9
+ program :version, Bind::VERSION::STRING
10
+ program :description, 'Bind actions to filesystem events'
11
+
12
+ command :to do |c|
13
+ set_common_options c
14
+ c.syntax = 'bind to <file> [file ...] [options] '
15
+ c.summary = 'Bind to modification of a file'
16
+ c.description = 'Bind to modification of a file or all files within a directory.'
17
+ c.example 'Bind to a single file, logging its path when changed', "bind change style.css -e 'puts file'"
18
+ c.option '-e', '--eval STRING', String, 'Evaluate a string of Ruby in context of Bind, so the file local variable is available.'
19
+ c.when_called do |args, options|
20
+ populate_common_options options
21
+ if options.eval
22
+ options.action = lambda { |file| eval options.eval }
23
+ else
24
+ abort 'invalid option. --eval switch is required in order to perform any action on the bound file(s)'
25
+ end
26
+ options.files = args
27
+ listener(options).run!
28
+ end
29
+ end
30
+
31
+ command :refresh do |c|
32
+ set_common_options c
33
+ c.syntax = 'bind refresh <uri> [options]'
34
+ c.summary = 'Bind to <uri>, refreshing browsers.'
35
+ c.description = 'Bind to <uri>, refreshing browsers when the files you are watching change.'
36
+ c.example = 'Bind a few css files for quick editing in multiple browsers', 'bind refresh http://localhost/page --files style.css,reset.css --browsers Safari,Firefox'
37
+ c.example = 'Bind local static html (no scheme)', 'bind refresh examples/demo.html -f style.css -b Safari'
38
+ c.option '-b', '--browsers BROWSERS', Array, 'List of browsers you wish to refresh. Defaults to Safari'
39
+ c.option '-f', '--files FILES', Array, 'List of files to bind to.'
40
+ c.when_called do |args, options|
41
+ populate_common_options options
42
+ path = expand_path args.shift
43
+ browsers = options.browsers || ['Safari']
44
+ options.action = Bind::Actions::RefreshBrowsers.new path, *browsers
45
+ abort 'invalid option. --files switch is required in order to bind' if options.files.nil?
46
+ listener(options).run!
47
+ end
48
+ end
@@ -0,0 +1,36 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{bind}
5
+ s.version = "0.0.2"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["TJ Holowaychuk"]
9
+ s.date = %q{2009-03-03}
10
+ s.default_executable = %q{bind}
11
+ s.description = %q{bind actions to filesystem events}
12
+ s.email = %q{tj@vision-media.ca}
13
+ s.executables = ["bind"]
14
+ s.extra_rdoc_files = ["bin/bind", "bind.gemspec", "lib/bind/actions/refresh_browsers.rb", "lib/bind/actions.rb", "lib/bind/command_helpers.rb", "lib/bind/listener.rb", "lib/bind/version.rb", "lib/bind.rb", "README.rdoc", "tasks/docs.rake", "tasks/gemspec.rake", "tasks/spec.rake"]
15
+ s.files = ["bin/bind", "bind.gemspec", "examples/demo.html", "examples/log_changes.rb", "examples/refresh_browsers.rb", "examples/style.css", "History.rdoc", "lib/bind/actions/refresh_browsers.rb", "lib/bind/actions.rb", "lib/bind/command_helpers.rb", "lib/bind/listener.rb", "lib/bind/version.rb", "lib/bind.rb", "Manifest", "Rakefile", "README.rdoc", "spec/bind_listener_spec.rb", "spec/fixtures/style.css", "spec/spec_helper.rb", "tasks/docs.rake", "tasks/gemspec.rake", "tasks/spec.rake", "Todo.rdoc"]
16
+ s.has_rdoc = true
17
+ s.homepage = %q{http://github.com/visionmedia/bind}
18
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Bind", "--main", "README.rdoc"]
19
+ s.require_paths = ["lib"]
20
+ s.rubyforge_project = %q{bind}
21
+ s.rubygems_version = %q{1.3.1}
22
+ s.summary = %q{bind actions to filesystem events}
23
+
24
+ if s.respond_to? :specification_version then
25
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
26
+ s.specification_version = 2
27
+
28
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
29
+ s.add_runtime_dependency(%q<visionmedia-commander>, [">= 2.4.6"])
30
+ else
31
+ s.add_dependency(%q<visionmedia-commander>, [">= 2.4.6"])
32
+ end
33
+ else
34
+ s.add_dependency(%q<visionmedia-commander>, [">= 2.4.6"])
35
+ end
36
+ end
@@ -0,0 +1,8 @@
1
+ <html>
2
+ <body>
3
+ <title>Bind Demo</title>
4
+ <link rel="stylesheet" href="style.css" />
5
+ </body>
6
+ <h1>Bind Demo</h1>
7
+ <p>Try binding to style.css and editing it, then watch bind update several browsers simaltaniously.</p>
8
+ </html>
@@ -0,0 +1,9 @@
1
+
2
+ require File.dirname(__FILE__) + '/../lib/bind'
3
+
4
+ # Execute this file to start the listener, then alter style.css a few times
5
+
6
+ style = File.dirname(__FILE__) + '/style.css'
7
+ action = lambda { |file| puts "modified #{file}" }
8
+ listener = Bind::Listener.new :event => :change, :files => [style], :interval => 1, :action => action, :timeout => 10, :log => $stdout
9
+ listener.run!
@@ -0,0 +1,10 @@
1
+
2
+ require File.dirname(__FILE__) + '/../lib/bind'
3
+
4
+ # Execute this file to start the listener, then alter style.css a few times
5
+
6
+ html = File.expand_path(File.dirname(__FILE__) + '/demo.html')
7
+ style = File.dirname(__FILE__) + '/style.css'
8
+ action = Bind::Actions::RefreshBrowsers.new html, 'Safari', 'Firefox'
9
+ listener = Bind::Listener.new :event => :change, :files => [style], :interval => 1, :action => action, :timeout => 60, :log => $stdout
10
+ listener.run!
@@ -0,0 +1,3 @@
1
+ h1 {
2
+ color: blue;
3
+ }
@@ -0,0 +1,28 @@
1
+ #--
2
+ # Copyright (c) 2009 TJ Holowaychuk <tj@vision-media.ca>
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ $:.unshift File.dirname(__FILE__)
25
+
26
+ require 'bind/version'
27
+ require 'bind/listener'
28
+ require 'bind/actions'
@@ -0,0 +1,6 @@
1
+
2
+ module Bind
3
+ module Actions
4
+ autoload :RefreshBrowsers, 'bind/actions/refresh_browsers'
5
+ end
6
+ end
@@ -0,0 +1,18 @@
1
+
2
+ module Bind
3
+ module Actions
4
+ class RefreshBrowsers
5
+
6
+ attr_accessor :browsers, :uri
7
+
8
+ def initialize uri, *browsers
9
+ @uri, @browsers = uri, browsers
10
+ end
11
+
12
+ def call file
13
+ @browsers.each { |browser| `open -g -a #{browser} #{uri}` }
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,27 @@
1
+
2
+ def set_common_options c
3
+ c.option '-i', '--interval SECONDS', Integer, 'Interval in seconds in which to listen for an event.'
4
+ c.option '-t', '--timeout SECONDS', Integer, 'Timeout after n seconds.'
5
+ c.option '-r', '--require LIBS', Array, 'Require ruby libraries.'
6
+ c.option '-V', '--verbose', 'Log information to STDOUT.'
7
+ end
8
+
9
+ def listener options
10
+ Bind::Listener.new options_to_hash(options)
11
+ end
12
+
13
+ def populate_common_options options
14
+ options.require.each { |lib| require lib } if options.require
15
+ options.debug = $stdout if options.verbose
16
+ end
17
+
18
+ def expand_path path
19
+ path.include?('://') ? path : File.expand_path(path)
20
+ end
21
+
22
+ def options_to_hash options
23
+ options.singleton_methods.inject({}) do |hash, meth|
24
+ hash[meth.to_sym] = options.send meth unless meth =~ /=$/
25
+ hash
26
+ end
27
+ end
@@ -0,0 +1,93 @@
1
+
2
+
3
+ module Bind
4
+ class Listener
5
+
6
+ attr_accessor :files, :action, :timeout, :interval, :event
7
+ attr_reader :run_time, :start_time, :finish_time
8
+
9
+ #--
10
+ # Exceptions
11
+ #++
12
+
13
+ class Error < StandardError; end
14
+
15
+ ##
16
+ # Event listener. Must specify the :files, and :action options.
17
+ #
18
+ # === Options:
19
+ #
20
+ # :files array of files and / or directories
21
+ # :action an object responding to #call, which is used as the callback for the event handler
22
+ # :timeout time in seconds, after which the listener should stop. Defaults to 0, meaning infinity
23
+ # :event event to bind to, may be one of (:change). Defaults to :change
24
+ # :debug log verbose debugging information to this stream
25
+ # :interval sleep interval in seconds. Defaults to 2
26
+ #
27
+
28
+ def initialize options = {}
29
+ @run_time, @mtimes = 0, {}
30
+ @files = options.fetch :files do
31
+ raise ArgumentError, 'specify one or more :files (or directories) to bind the listener to'
32
+ end
33
+ @action = options.fetch :action do
34
+ raise ArgumentError, 'pass a valid :action responding to #call'
35
+ end
36
+ @log = options.fetch :debug, false
37
+ @timeout = options.fetch :timeout, 0
38
+ @interval = options.fetch :interval, 2
39
+ @event = options.fetch :event, :change
40
+ end
41
+
42
+ ##
43
+ # Start the listener.
44
+
45
+ def run!
46
+ start_time = Time.now
47
+ log "binding to #{files.join(', ')}, watching #{event} every #{interval} second(s)." +
48
+ (timeout > 0 ? " Terminating in #{timeout} seconds" : '')
49
+ catch :halt do
50
+ loop do
51
+ @run_time = Time.now - start_time
52
+ throw :halt if timeout > 0 and @run_time >= timeout
53
+ log '.', true
54
+ files.each { |file| send event, File.new(file) }
55
+ sleep interval
56
+ end
57
+ end
58
+ finish_time = Time.now
59
+ log "binding terminated"
60
+ end
61
+
62
+ private
63
+
64
+ ##
65
+ # Handle change event.
66
+
67
+ def change file
68
+ if changed? file
69
+ log "changed #{file.path}"
70
+ action.call file
71
+ @mtimes[file.path] = file.mtime
72
+ end
73
+ end
74
+
75
+ ##
76
+ # Check if +file+ has been modified since the last check.
77
+
78
+ def changed? file
79
+ file.mtime > (@mtimes[file.path] ||= file.mtime)
80
+ end
81
+
82
+ ##
83
+ # Optionally log a +message+ when a stream has been specified.
84
+
85
+ def log message, print = false
86
+ if @log
87
+ print ? @log.print(message) : @log.puts(message)
88
+ @log.flush
89
+ end
90
+ end
91
+
92
+ end
93
+ end
@@ -0,0 +1,7 @@
1
+
2
+ module Bind
3
+ module VERSION #:nodoc:
4
+ MAJOR, MINOR, TINY = 0, 0, 2
5
+ STRING = [MAJOR, MINOR, TINY].join '.'
6
+ end
7
+ end
@@ -0,0 +1,14 @@
1
+
2
+ describe Bind::Listener do
3
+
4
+ def listener &action
5
+ Bind::Listener.new :event => :change, :files => [File.dirname(__FILE__) + '/fixtures/style.css'], :interval => 1, :action => action, :timeout => 2
6
+ end
7
+
8
+ it "should record total runtime" do
9
+ l = listener {}
10
+ l.run!
11
+ l.run_time.to_i.should == 2
12
+ end
13
+
14
+ end
File without changes
@@ -0,0 +1,2 @@
1
+
2
+ require 'bind'
@@ -0,0 +1,13 @@
1
+
2
+ namespace :docs do
3
+
4
+ desc 'Remove rdoc products'
5
+ task :remove => [:clobber_docs]
6
+
7
+ desc 'Build docs, and open in browser for viewing (specify BROWSER)'
8
+ task :open do
9
+ browser = ENV["BROWSER"] || "safari"
10
+ sh "open -a #{browser} doc/index.html"
11
+ end
12
+
13
+ end
@@ -0,0 +1,3 @@
1
+
2
+ desc 'Build gemspec file'
3
+ task :gemspec => [:build_gemspec]
@@ -0,0 +1,25 @@
1
+
2
+ require 'spec/rake/spectask'
3
+
4
+ desc "Run all specifications"
5
+ Spec::Rake::SpecTask.new(:spec) do |t|
6
+ t.libs << "lib"
7
+ t.spec_opts = ["--color", "--require", "spec/spec_helper.rb"]
8
+ end
9
+
10
+ namespace :spec do
11
+
12
+ desc "Run all specifications verbosely"
13
+ Spec::Rake::SpecTask.new(:verbose) do |t|
14
+ t.libs << "lib"
15
+ t.spec_opts = ["--color", "--format", "specdoc", "--require", "spec/spec_helper.rb"]
16
+ end
17
+
18
+ desc "Run specific specification verbosely (specify SPEC)"
19
+ Spec::Rake::SpecTask.new(:select) do |t|
20
+ t.libs << "lib"
21
+ t.spec_files = [ENV["SPEC"]]
22
+ t.spec_opts = ["--color", "--format", "specdoc", "--require", "spec/spec_helper.rb"]
23
+ end
24
+
25
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: visionmedia-bind
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - TJ Holowaychuk
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-03 00:00:00 -08:00
13
+ default_executable: bind
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: visionmedia-commander
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.4.6
24
+ version:
25
+ description: bind actions to filesystem events
26
+ email: tj@vision-media.ca
27
+ executables:
28
+ - bind
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - bin/bind
33
+ - bind.gemspec
34
+ - lib/bind/actions/refresh_browsers.rb
35
+ - lib/bind/actions.rb
36
+ - lib/bind/command_helpers.rb
37
+ - lib/bind/listener.rb
38
+ - lib/bind/version.rb
39
+ - lib/bind.rb
40
+ - README.rdoc
41
+ - tasks/docs.rake
42
+ - tasks/gemspec.rake
43
+ - tasks/spec.rake
44
+ files:
45
+ - bin/bind
46
+ - bind.gemspec
47
+ - examples/demo.html
48
+ - examples/log_changes.rb
49
+ - examples/refresh_browsers.rb
50
+ - examples/style.css
51
+ - History.rdoc
52
+ - lib/bind/actions/refresh_browsers.rb
53
+ - lib/bind/actions.rb
54
+ - lib/bind/command_helpers.rb
55
+ - lib/bind/listener.rb
56
+ - lib/bind/version.rb
57
+ - lib/bind.rb
58
+ - Manifest
59
+ - Rakefile
60
+ - README.rdoc
61
+ - spec/bind_listener_spec.rb
62
+ - spec/fixtures/style.css
63
+ - spec/spec_helper.rb
64
+ - tasks/docs.rake
65
+ - tasks/gemspec.rake
66
+ - tasks/spec.rake
67
+ - Todo.rdoc
68
+ has_rdoc: true
69
+ homepage: http://github.com/visionmedia/bind
70
+ post_install_message:
71
+ rdoc_options:
72
+ - --line-numbers
73
+ - --inline-source
74
+ - --title
75
+ - Bind
76
+ - --main
77
+ - README.rdoc
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: "0"
85
+ version:
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: "1.2"
91
+ version:
92
+ requirements: []
93
+
94
+ rubyforge_project: bind
95
+ rubygems_version: 1.2.0
96
+ signing_key:
97
+ specification_version: 2
98
+ summary: bind actions to filesystem events
99
+ test_files: []
100
+