kicker 3.0.0 → 4.0.0.p1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,40 @@
1
+ class Kicker
2
+ module CoreExt
3
+ module Array
4
+ # Deletes elements from self for which the block evaluates to +true+. A new
5
+ # array is returned with those values the block returned. So basically, a
6
+ # combination of reject! and map.
7
+ #
8
+ # a = [1,2,3]
9
+ # b = a.take_and_map { |x| x * 2 if x == 2 }
10
+ # b # => [4]
11
+ # a # => [1, 3]
12
+ #
13
+ # If +pattern+ is specified then files matching the pattern will be taken.
14
+ #
15
+ # a = [ 'bar', 'foo/bar' ]
16
+ # b = a.take_and_map('*/bar') { |x| x }
17
+ # b # => ['foo/bar']
18
+ # a # => ['bar']
19
+ #
20
+ # If +flatten_and_compact+ is +true+, the result array will be flattened
21
+ # and compacted. The default is +true+.
22
+ def take_and_map(pattern = nil, flatten_and_compact = true)
23
+ took = []
24
+ reject! do |x|
25
+ next if pattern and !File.fnmatch?(pattern, x)
26
+ if result = yield(x)
27
+ took << result
28
+ end
29
+ end
30
+ if flatten_and_compact
31
+ took.flatten!
32
+ took.compact!
33
+ end
34
+ took
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ Array.send(:include, Kicker::CoreExt::Array)
@@ -0,0 +1,5 @@
1
+ class Kicker
2
+ def self.debug(message)
3
+ $stderr.puts(::Kicker.formatter.call(Time.now, message))
4
+ end
5
+ end
@@ -0,0 +1,14 @@
1
+ class Kicker
2
+ module Deprecated
3
+ def execute(command)
4
+ Kicker.debug("[DEPRECATED] Calling `execute' directly is deprecated, instead use `watcher.execute'. Called from #{_last_caller(caller)}.")
5
+ watcher.execute(command)
6
+ end
7
+
8
+ private
9
+
10
+ def _last_caller(stack)
11
+ stack[0]
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ class Kicker
2
+ module Formatter
3
+ def formatters
4
+ @formatters ||= {
5
+ silent: Proc.new {},
6
+ quiet: Proc.new { |time, message| message },
7
+ regular: Proc.new { |time, message| time.strftime('%H:%M:%S.') + time.usec.to_s[0,2] + ' | ' + message }
8
+ }
9
+ end
10
+
11
+ def formatter(name=:regular)
12
+ formatters[name]
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,37 @@
1
+ class Kicker
2
+ # Parser for command line options
3
+ class OptionParser
4
+ # Parses ARGV from a Ruby script and returns options and arguments without
5
+ # switch as arrays.
6
+ #
7
+ # OptionParser.parse(%w(create --username manfred -r 1 -r 2)) #=>
8
+ # [[["username", "manfred"], ["r", "1"], ["r", "2"]], ["create"]]
9
+ def self.parse(argv)
10
+ return [[],[]] if argv.empty?
11
+
12
+ options = []
13
+ rest = []
14
+ switch = nil
15
+
16
+ for value in argv
17
+ bytes = value.respond_to?(:bytes) ? value.bytes.first(2) : [value[0], value[1]]
18
+ # value is a switch
19
+ if bytes[0] == 45
20
+ switch = value.slice((bytes[1] == 45 ? 2 : 1)..-1)
21
+ options << [switch]
22
+ else
23
+ if switch
24
+ # we encountered another switch so this
25
+ # value belongs to the last switch
26
+ options[-1] << value
27
+ switch = nil
28
+ else
29
+ rest << value
30
+ end
31
+ end
32
+ end
33
+
34
+ [options, rest]
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,2 @@
1
+ def ignore(expressions)
2
+ end
@@ -0,0 +1,54 @@
1
+ require 'benchmark'
2
+
3
+ class Peck
4
+ attr_reader :cwd, :watcher
5
+
6
+ def initialize(cwd: Dir.pwd, watcher: nil)
7
+ @cwd = cwd
8
+ @watcher = watcher
9
+ end
10
+
11
+ def all_specs
12
+ Dir.glob(File.join(@cwd, 'test/**/*_test.rb'))
13
+ end
14
+
15
+ def peck
16
+ "bundle exec peck"
17
+ end
18
+
19
+ def format_time(seconds)
20
+ if seconds < 1
21
+ "#{(seconds * 1000).round} ms"
22
+ else
23
+ "#{(seconds * 100).round / 100.0} sec"
24
+ end
25
+ end
26
+
27
+ def execute_specs(files)
28
+ return if files.empty?
29
+ realtime = (Benchmark.realtime {
30
+ watcher.execute("#{peck} #{files.join(' ')}")
31
+ })
32
+ watcher.report "Running specs took #{format_time(realtime)}."
33
+ end
34
+
35
+ def map_to_specs(filename)
36
+ Dir.glob(File.join(cwd, "test/**/#{File.basename(filename, '.rb')}_test.rb"))
37
+ end
38
+
39
+ def call(file_or_path, flags)
40
+ ::Kicker.debug("Peck recipe: #{file_or_path}")
41
+ specs = []
42
+ case file_or_path
43
+ when %r{_test\.rb$}
44
+ specs << file_or_path
45
+ when %r{\.rb$}
46
+ specs.concat map_to_specs(file_or_path)
47
+ when %r{\Aapp/views/([\w\\]+)/[^/]+\Z}
48
+ specs.concat map_to_specs($1 + '_controller.rb')
49
+ end
50
+ execute_specs(specs)
51
+ end
52
+ end
53
+
54
+ process(Peck.new(cwd: cwd, watcher: watcher))
File without changes
@@ -1,4 +1,4 @@
1
- class Kicker::Recipes::Ruby
1
+ class Ruby
2
2
  class << self
3
3
  # Assigns the type of tests to run. Eg: `test' or `spec'.
4
4
  attr_writer :test_type
@@ -149,15 +149,15 @@ class Kicker::Recipes::Ruby
149
149
  end
150
150
  end
151
151
 
152
- options.on('-b', '--ruby [PATH]', "Use an alternate Ruby binary for spawned test runners. (Default is `ruby')") do |command|
153
- Kicker::Recipes::Ruby.runner_bin = command
152
+ # Support for Kicker 3.0 recipes
153
+ class Kicker
154
+ class Recipes
155
+ Ruby = Ruby
156
+ end
154
157
  end
155
158
 
156
- recipe :ruby do
157
- process Kicker::Recipes::Ruby
159
+ # options.on('-b', '--ruby [PATH]', "Use an alternate Ruby binary for spawned test runners. (Default is `ruby')") do |command|
160
+ # Kicker::Recipes::Ruby.runner_bin = command
161
+ # end
158
162
 
159
- # When changing the Gemfile, install dependencies
160
- process do |files|
161
- execute 'bundle install' if files.delete('Gemfile')
162
- end
163
- end
163
+ process(Ruby)
@@ -0,0 +1,77 @@
1
+ class Kicker
2
+ class Script
3
+ class Context
4
+ attr_accessor :cwd, :watcher, :script
5
+
6
+ include Kicker::Deprecated
7
+
8
+ def initialize(cwd: Dir.pwd, watcher: nil, script: nil)
9
+ @cwd = cwd
10
+ @watcher = watcher
11
+ @script = script
12
+ end
13
+
14
+ def recipe(name)
15
+ filename = File.join(::Kicker::Script.recipes_path, name.to_s + '.rb')
16
+ if File.exist?(filename)
17
+ ::Kicker.debug("Loading recipe: #{filename}")
18
+ load(filename)
19
+ else
20
+ ::Kicker.debug("Unknown recipe: #{name}")
21
+ end
22
+ end
23
+
24
+ def load(filename)
25
+ eval(File.read(filename), binding, filename)
26
+ end
27
+
28
+ def process(callable=nil, &block)
29
+ processor = callable || block
30
+ ::Kicker.debug("Adding processor: #{processor}")
31
+ script.processors << processor
32
+ end
33
+ end
34
+
35
+ class << self
36
+ attr_accessor :recipes_path
37
+ end
38
+ self.recipes_path = File.expand_path('recipe', __dir__)
39
+
40
+ attr_accessor :cwd, :watcher, :recipes, :processors
41
+
42
+ def initialize(cwd: Dir.pwd, watcher: nil)
43
+ @cwd = cwd
44
+ @watcher = watcher
45
+ @recipes = []
46
+ @processors = []
47
+ @context = Kicker::Script::Context.new(cwd: @cwd, watcher: @watcher, script: self)
48
+ end
49
+
50
+ def recipe(name)
51
+ @context.recipe(name)
52
+ end
53
+
54
+ def load(filename)
55
+ @context.load(filename)
56
+ end
57
+
58
+ def call(file_or_path, flags)
59
+ @processors.each do |processor|
60
+ case processor.method(:call).arity
61
+ when 0
62
+ processor.call
63
+ when 1
64
+ processor.call([file_or_path])
65
+ else
66
+ processor.call(file_or_path, flags)
67
+ end
68
+ end
69
+ end
70
+
71
+ def self.available_recipes
72
+ Dir.glob(File.join(recipes_path, '*.rb')).map do |filename|
73
+ File.basename(filename, '.rb')
74
+ end
75
+ end
76
+ end
77
+ end
@@ -1,3 +1,3 @@
1
1
  class Kicker
2
- VERSION = "3.0.0"
3
- end
2
+ VERSION = '4.0.0.p1'
3
+ end
@@ -0,0 +1,113 @@
1
+ require 'pty'
2
+
3
+ class Kicker
4
+ class Watcher
5
+ class << self
6
+ attr_accessor :buffer_size
7
+ end
8
+
9
+ self.buffer_size = 1
10
+
11
+ KICKFILES = %w(Kickfile .kick)
12
+ CLEAR = "\e[H\e[2J"
13
+
14
+ def initialize(options={})
15
+ @options = options
16
+ Kicker.debug("Watcher options: #{@options}")
17
+
18
+ @buffer_size = self.class.buffer_size
19
+
20
+ @out = options[:out] || $stdout
21
+
22
+ @cwd = Dir.pwd
23
+ @script = Script.new(watcher: self, cwd: @cwd)
24
+
25
+ load
26
+ end
27
+
28
+ def load_kickfile
29
+ if @options[:kickfile]
30
+ Kicker.debug("Loading Kickfile from: #{@options[:kickfile]}")
31
+ @script.load(@options[:kickfile])
32
+ true
33
+ else
34
+ false
35
+ end
36
+ end
37
+
38
+ def load_default_kickfile
39
+ loaded = false
40
+ KICKFILES.each do |path|
41
+ kickfile = File.join(@cwd, path)
42
+ if File.exist?(kickfile)
43
+ Kicker.debug("Loading Kickfile from: #{kickfile}")
44
+ @script.load(kickfile)
45
+ loaded = true
46
+ end
47
+ end
48
+ loaded
49
+ end
50
+
51
+ def load_recipes
52
+ @options[:recipes].each do |recipe|
53
+ @script.recipe(recipe)
54
+ end if @options[:recipes]
55
+ end
56
+
57
+ def load
58
+ load_kickfile || load_default_kickfile
59
+ load_recipes
60
+ end
61
+
62
+ def clear_before_execute?
63
+ @options[:clear_before_execute] == true
64
+ end
65
+
66
+ def verbosity
67
+ @options[:verbosity] || :regular
68
+ end
69
+
70
+ def formatter_for_verbosity
71
+ Kicker.formatter(verbosity)
72
+ end
73
+
74
+ def report(message)
75
+ unless verbosity == :silent
76
+ @out.puts(formatter_for_verbosity.call(Time.now, message))
77
+ end
78
+ end
79
+
80
+ def write(buffer)
81
+ @out.write(buffer)
82
+ end
83
+
84
+ def clear
85
+ write(CLEAR)
86
+ end
87
+
88
+ def execute(command)
89
+ clear if clear_before_execute?
90
+ report("Executing: #{command}")
91
+ write("\n") unless verbosity == :silent
92
+ PTY.open do |master, slave|
93
+ read, write = IO.pipe
94
+ pid = spawn(command, in: read, out: slave)
95
+ read.close
96
+ slave.close
97
+ while(buffer = master.read(@buffer_size))
98
+ write(buffer)
99
+ end
100
+ end
101
+ write("\n")
102
+ end
103
+
104
+ def run
105
+ report("Started watching: #{@cwd}")
106
+ Tidings.watch(@cwd) do |file_or_path, flags|
107
+ file_or_path = file_or_path[@cwd.length+1..-1]
108
+ Kicker.debug("Event: #{file_or_path}: #{flags.inspect}")
109
+ @script.call(file_or_path, flags)
110
+ end
111
+ end
112
+ end
113
+ end
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kicker
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
5
- prerelease:
4
+ version: 4.0.0.p1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Eloy Duran
@@ -10,105 +9,24 @@ authors:
10
9
  autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2013-12-03 00:00:00.000000000 Z
12
+ date: 2014-04-03 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
- name: listen
15
+ name: tidings
17
16
  requirement: !ruby/object:Gem::Requirement
18
- none: false
19
17
  requirements:
20
- - - ~>
21
- - !ruby/object:Gem::Version
22
- version: 1.3.0
23
- type: :runtime
24
- prerelease: false
25
- version_requirements: !ruby/object:Gem::Requirement
26
- none: false
27
- requirements:
28
- - - ~>
29
- - !ruby/object:Gem::Version
30
- version: 1.3.0
31
- - !ruby/object:Gem::Dependency
32
- name: notify
33
- requirement: !ruby/object:Gem::Requirement
34
- none: false
35
- requirements:
36
- - - ~>
37
- - !ruby/object:Gem::Version
38
- version: 0.5.2
39
- type: :runtime
40
- prerelease: false
41
- version_requirements: !ruby/object:Gem::Requirement
42
- none: false
43
- requirements:
44
- - - ~>
45
- - !ruby/object:Gem::Version
46
- version: 0.5.2
47
- - !ruby/object:Gem::Dependency
48
- name: bacon
49
- requirement: !ruby/object:Gem::Requirement
50
- none: false
51
- requirements:
52
- - - ! '>='
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- type: :development
56
- prerelease: false
57
- version_requirements: !ruby/object:Gem::Requirement
58
- none: false
59
- requirements:
60
- - - ! '>='
61
- - !ruby/object:Gem::Version
62
- version: '0'
63
- - !ruby/object:Gem::Dependency
64
- name: mocha-on-bacon
65
- requirement: !ruby/object:Gem::Requirement
66
- none: false
67
- requirements:
68
- - - ! '>='
69
- - !ruby/object:Gem::Version
70
- version: '0'
71
- type: :development
72
- prerelease: false
73
- version_requirements: !ruby/object:Gem::Requirement
74
- none: false
75
- requirements:
76
- - - ! '>='
77
- - !ruby/object:Gem::Version
78
- version: '0'
79
- - !ruby/object:Gem::Dependency
80
- name: activesupport
81
- requirement: !ruby/object:Gem::Requirement
82
- none: false
83
- requirements:
84
- - - ! '>='
18
+ - - ">="
85
19
  - !ruby/object:Gem::Version
86
20
  version: '0'
87
- type: :development
88
- prerelease: false
89
- version_requirements: !ruby/object:Gem::Requirement
90
- none: false
91
- requirements:
92
- - - ! '>='
93
- - !ruby/object:Gem::Version
94
- version: '0'
95
- - !ruby/object:Gem::Dependency
96
- name: fakefs
97
- requirement: !ruby/object:Gem::Requirement
98
- none: false
99
- requirements:
100
- - - ! '>='
101
- - !ruby/object:Gem::Version
102
- version: '0'
103
- type: :development
21
+ type: :runtime
104
22
  prerelease: false
105
23
  version_requirements: !ruby/object:Gem::Requirement
106
- none: false
107
24
  requirements:
108
- - - ! '>='
25
+ - - ">="
109
26
  - !ruby/object:Gem::Version
110
27
  version: '0'
111
- description: Allows you to fire specific command on file-system change.
28
+ description: Kicker lets you watch filesystem changes and act in them with predefined
29
+ or custom recipes.
112
30
  email:
113
31
  - eloy.de.enige@gmail.com
114
32
  - manfred@fngtps.com
@@ -116,53 +34,47 @@ executables:
116
34
  - kicker
117
35
  extensions: []
118
36
  extra_rdoc_files:
119
- - LICENSE
37
+ - COPYING
120
38
  - README.rdoc
121
39
  files:
40
+ - COPYING
41
+ - README.rdoc
122
42
  - bin/kicker
123
- - lib/kicker/callback_chain.rb
124
- - lib/kicker/core_ext.rb
125
- - lib/kicker/fsevents.rb
126
- - lib/kicker/job.rb
127
- - lib/kicker/notification.rb
128
- - lib/kicker/options.rb
129
- - lib/kicker/recipes/could_not_handle_file.rb
130
- - lib/kicker/recipes/dot_kick.rb
131
- - lib/kicker/recipes/execute_cli_command.rb
132
- - lib/kicker/recipes/ignore.rb
133
- - lib/kicker/recipes/jstest.rb
134
- - lib/kicker/recipes/rails.rb
135
- - lib/kicker/recipes/ruby.rb
136
- - lib/kicker/recipes.rb
137
- - lib/kicker/utils.rb
138
- - lib/kicker/version.rb
139
43
  - lib/kicker.rb
140
- - README.rdoc
141
- - LICENSE
142
- homepage: http://github.com/alloy/kicker
143
- licenses:
144
- - MIT
44
+ - lib/kicker/cli.rb
45
+ - lib/kicker/core_ext/array.rb
46
+ - lib/kicker/debug.rb
47
+ - lib/kicker/deprecated.rb
48
+ - lib/kicker/formatter.rb
49
+ - lib/kicker/option_parser.rb
50
+ - lib/kicker/recipe/ignore.rb
51
+ - lib/kicker/recipe/peck.rb
52
+ - lib/kicker/recipe/reload.rb
53
+ - lib/kicker/recipe/ruby.rb
54
+ - lib/kicker/script.rb
55
+ - lib/kicker/version.rb
56
+ - lib/kicker/watcher.rb
57
+ homepage: http://github.com/Manfred/kicker
58
+ licenses: []
59
+ metadata: {}
145
60
  post_install_message:
146
61
  rdoc_options: []
147
62
  require_paths:
148
63
  - lib
149
- - vendor
150
64
  required_ruby_version: !ruby/object:Gem::Requirement
151
- none: false
152
65
  requirements:
153
- - - ! '>='
66
+ - - ">="
154
67
  - !ruby/object:Gem::Version
155
68
  version: '0'
156
69
  required_rubygems_version: !ruby/object:Gem::Requirement
157
- none: false
158
70
  requirements:
159
- - - ! '>='
71
+ - - ">"
160
72
  - !ruby/object:Gem::Version
161
- version: '0'
73
+ version: 1.3.1
162
74
  requirements: []
163
75
  rubyforge_project:
164
- rubygems_version: 1.8.23
76
+ rubygems_version: 2.2.2
165
77
  signing_key:
166
- specification_version: 3
78
+ specification_version: 4
167
79
  summary: A lean, agnostic, flexible file-change watcher.
168
80
  test_files: []