jbarnette-lather 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown ADDED
@@ -0,0 +1,87 @@
1
+ # Lather
2
+
3
+ Lather is an easy way to watch files and do something when they
4
+ change. By default, it checks for changes every second.
5
+
6
+ ## From the Command Line
7
+
8
+ The `lather` command-line tool lets you quickly track changes to a set
9
+ of files.
10
+
11
+ $ lather 'test/**/*_test.rb'
12
+
13
+ By default, `lather` will print a message each time a file matching
14
+ your spec changes. `**` is supported for recursive globbing, but make
15
+ sure to escape/quote the glob so your shell doesn't expand it.
16
+
17
+ You can also run a command every time something changes:
18
+
19
+ $ lather -r 'rake test' '{lib,test}/**/*.rb'
20
+
21
+ ## From Code
22
+
23
+ require "rubygems"
24
+ require "lather"
25
+
26
+ watcher = Lather::Watcher.new "**/*.rb" do |changed|
27
+ puts "Files changed: #{changed.join(' ')}"
28
+ end
29
+
30
+ watcher.go!
31
+
32
+ If you want to mess with the polling interval:
33
+
34
+ # :sleep is in seconds
35
+ Lather::Watcher.new "*.rb", :sleep => 5
36
+
37
+ ## Installing
38
+
39
+ $ [sudo] gem install jbarnette-lather -s http://gems.github.com
40
+
41
+ ## Hacking
42
+
43
+ **The tests aren't working right this second. Check back in a bit.**
44
+ Make sure you have minitest installed. `rake lather` will watch `lib`
45
+ and `test` and re-run the tests when something changes. If you're
46
+ looking for something to work on, think about these:
47
+
48
+ * A `:force => true` option for `Lather::Watcher` so it'll call the
49
+ change proc with all matched files when it first starts.
50
+
51
+ * A way to get at the list of changed files in a `-r` command.
52
+
53
+ * Some default exclude (like backup/editor files, `.svn`, `.git`)
54
+ patterns, and an easy way to add new ones.
55
+
56
+ * A `--sleep <secs>` switch for the command-line tool.
57
+
58
+ ## Thanks
59
+
60
+ Lather owes a huge debt to [Ryan Davis'][ryan] [ZenTest][zt],
61
+ specifically `autotest`. Use it. It'll change your life.
62
+
63
+ [ryan]: http://blog.zenspider.com
64
+ [zt]: http://www.zenspider.com/ZSS/Products/ZenTest
65
+
66
+ ## License
67
+
68
+ Copyright 2009 John Barnette [jbarnette@gmail.com]
69
+
70
+ Permission is hereby granted, free of charge, to any person obtaining
71
+ a copy of this software and associated documentation files (the
72
+ 'Software'), to deal in the Software without restriction, including
73
+ without limitation the rights to use, copy, modify, merge, publish,
74
+ distribute, sublicense, and/or sell copies of the Software, and to
75
+ permit persons to whom the Software is furnished to do so, subject to
76
+ the following conditions:
77
+
78
+ The above copyright notice and this permission notice shall be
79
+ included in all copies or substantial portions of the Software.
80
+
81
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
82
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
83
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
84
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
85
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
86
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
87
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,46 @@
1
+ require "rubygems"
2
+ require "rubygems/specification"
3
+
4
+ require "./lib/lather"
5
+
6
+ namespace :gem do
7
+ desc "Update the gemspec."
8
+ task :spec do
9
+ spec = Gem::Specification.new do |s|
10
+ s.name = "lather"
11
+ s.version = Lather::VERSION
12
+ s.platform = Gem::Platform::RUBY
13
+ s.has_rdoc = false
14
+ s.summary = "Lather rinses and repeats."
15
+ s.description = s.summary
16
+ s.author = "John Barnette"
17
+ s.email = "jbarnette@gmail.com"
18
+ s.homepage = "http://github.com/jbarnette/lather"
19
+ s.require_path = "lib"
20
+ s.bindir = "bin"
21
+ s.executables = %w(lather)
22
+
23
+ s.files = %w(Rakefile README.markdown) + Dir["{bin,lib,test}/**/*"]
24
+ end
25
+
26
+ File.open("#{spec.name}.gemspec", "w") do |f|
27
+ f.puts spec.to_ruby
28
+ end
29
+ end
30
+ end
31
+
32
+ desc "Run tests."
33
+ task :test do
34
+ testify
35
+ end
36
+
37
+ desc "Rinse, repeat."
38
+ task :lather do
39
+ Lather::Watcher.new("{lib,test}/**/*.rb") { testify }.go!
40
+ end
41
+
42
+ def testify
43
+ puts `ruby -Ilib:test #{Dir['test/**/*_test.rb'].join(' ')}`
44
+ end
45
+
46
+ task :default => :test
data/bin/lather ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby -w
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/lather")
4
+ require "lather/cli"
5
+
6
+ trap("INT") { puts; exit 1 }
7
+ Lather::Cli.new.go! ARGV
data/lib/lather.rb ADDED
@@ -0,0 +1,6 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) ||
3
+ $:.include?(File.expand_path(File.dirname(__FILE__)))
4
+
5
+ require "lather/version"
6
+ require "lather/watcher"
data/lib/lather/cli.rb ADDED
@@ -0,0 +1,70 @@
1
+ require "optparse"
2
+
3
+ require "lather/watcher"
4
+ require "lather/version"
5
+
6
+ module Lather
7
+ class Cli
8
+ def initialize
9
+ @command = nil
10
+ @globs = []
11
+ @verbose = false
12
+
13
+ @options = OptionParser.new do |o|
14
+ o.banner = "#$0 [-hVv] [-r <cmd>] <globs...>"
15
+ o.separator ""
16
+
17
+ o.on "--help", "-h", "-?", "Shows help." do
18
+ exit help!
19
+ end
20
+
21
+ o.on "--verbose", "-v", "Talks your ear off." do
22
+ @verbose = true
23
+ end
24
+
25
+ o.on "--version", "-V", "Prints #{Lather::VERSION}." do
26
+ puts Lather::VERSION
27
+ exit
28
+ end
29
+
30
+ o.on "--rinse [cmd]", "--run", "-r", "Runs when things change." do |cmd|
31
+ @command = cmd
32
+ end
33
+
34
+ o.separator ""
35
+ end
36
+ end
37
+
38
+ def parse! args
39
+ @options.parse! args
40
+ @globs.concat args
41
+ exit help! if @globs.empty?
42
+ end
43
+
44
+ def go! args
45
+ parse! args
46
+
47
+ watcher = Lather::Watcher.new @globs do |files|
48
+ if @command
49
+ system @command
50
+ else
51
+ puts "Changed: #{files.join(" ")}"
52
+ end
53
+ end
54
+
55
+ verbose "Watching: #{watcher.files.keys.sort.join(" ")}"
56
+ watcher.go!
57
+ end
58
+
59
+ private
60
+
61
+ def verbose *args
62
+ puts args.join(" ") if @verbose
63
+ end
64
+
65
+ def help!
66
+ puts @options
67
+ 1 # process exit code
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,3 @@
1
+ module Lather
2
+ VERSION = "1.0.1"
3
+ end
@@ -0,0 +1,49 @@
1
+ module Lather
2
+ class Watcher
3
+ attr_reader :files
4
+
5
+ def initialize *globs, &callback
6
+ raise ArgumentError, "need a callback" unless block_given?
7
+ @callback = callback
8
+
9
+ @options = { :sleep => 1 }
10
+ @options.merge!(globs.pop) if globs.last.is_a? Hash
11
+
12
+ @globs = globs
13
+ @files = find_files
14
+ end
15
+
16
+ def go!
17
+ @timestamp = Time.now
18
+
19
+ loop do
20
+ unless (changed = update_files_and_timestamp).empty?
21
+ @callback[changed]
22
+ end
23
+
24
+ Kernel.sleep @options[:sleep]
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def update_files_and_timestamp
31
+ @files = find_files
32
+ updated = @files.keys.select { |k| @files[k] > @timestamp }
33
+ @timestamp = @files.values.max
34
+
35
+ updated
36
+ end
37
+
38
+ def find_files
39
+ files = {}
40
+
41
+ @globs.flatten.collect { |g| Dir[g] }.flatten.each do |file|
42
+ # silently skip stat failures: file deleted, etc.
43
+ files[file] = File.stat(file).mtime rescue next
44
+ end
45
+
46
+ files
47
+ end
48
+ end
49
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,4 @@
1
+ require "rubygems"
2
+ require "minitest/autorun"
3
+
4
+ require "lather"
@@ -0,0 +1,29 @@
1
+ require "helper"
2
+ require "lather/cli"
3
+
4
+ module Lather
5
+ class CliTest < MiniTest::Unit::TestCase
6
+ def setup
7
+ @cli = Lather::Cli.new
8
+ def @cli.exit *args; throw :exit end
9
+ end
10
+
11
+ def parse! *args
12
+ capture_io do
13
+ catch(:exit) { @cli.parse! args }
14
+ end
15
+ end
16
+
17
+ def test_empty_invocation_prints_help
18
+ out, err = parse!
19
+ assert_match /Shows help/, out
20
+ end
21
+
22
+ def test_V_option_prints_version
23
+ %w(-V --version).each do |flag|
24
+ out, err = parse! flag
25
+ assert_equal Lather::VERSION, out.chomp
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,11 @@
1
+ require "helper"
2
+
3
+ module Lather
4
+ class WatcherTest < MiniTest::Unit::TestCase
5
+ def test_initialize_complains_without_a_callback
6
+ assert_raise ArgumentError do
7
+ Lather::Watcher.new
8
+ end
9
+ end
10
+ end
11
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jbarnette-lather
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - John Barnette
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-01-28 00:00:00 -08:00
13
+ default_executable: lather
14
+ dependencies: []
15
+
16
+ description: Lather rinses and repeats.
17
+ email: jbarnette@gmail.com
18
+ executables:
19
+ - lather
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - Rakefile
26
+ - README.markdown
27
+ - bin/lather
28
+ - lib/lather
29
+ - lib/lather/cli.rb
30
+ - lib/lather/version.rb
31
+ - lib/lather/watcher.rb
32
+ - lib/lather.rb
33
+ - test/helper.rb
34
+ - test/lather
35
+ - test/lather/cli_test.rb
36
+ - test/lather/watcher_test.rb
37
+ has_rdoc: false
38
+ homepage: http://github.com/jbarnette/lather
39
+ post_install_message:
40
+ rdoc_options: []
41
+
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ version:
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ requirements: []
57
+
58
+ rubyforge_project:
59
+ rubygems_version: 1.2.0
60
+ signing_key:
61
+ specification_version: 2
62
+ summary: Lather rinses and repeats.
63
+ test_files: []
64
+