sidekick 0.4.2 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.sidekick +1 -1
- data/README.textile +12 -81
- data/Rakefile +3 -1
- data/VERSION +1 -1
- data/lib/sidekick.rb +47 -81
- data/lib/sidekick/helpers.rb +28 -54
- data/lib/sidekick/helpers/util.rb +26 -0
- data/lib/sidekick/triggers.rb +15 -14
- data/lib/template +1 -1
- data/sidekick.gemspec +9 -3
- metadata +31 -5
- data/lib/sidekick/triggers/watch.rb +0 -55
data/.sidekick
CHANGED
data/README.textile
CHANGED
@@ -7,39 +7,24 @@ h3. Use cases
|
|
7
7
|
|
8
8
|
* Restart server when code is changed
|
9
9
|
* Compile Sass and CoffeeScript templates when they are updated
|
10
|
+
* Periodically run commands
|
10
11
|
* Continuous testing, with notifications and flexible hooks
|
11
|
-
* Periodically running commands
|
12
12
|
|
13
|
-
You typically run Sidekick in the background
|
13
|
+
You typically run Sidekick in the background to automate this while coding.
|
14
14
|
|
15
15
|
h3. Features
|
16
16
|
|
17
|
-
* Simple and powerful DSL
|
18
|
-
*
|
19
|
-
*
|
20
|
-
*
|
21
|
-
*
|
22
|
-
|
23
|
-
|
17
|
+
* Simple and powerful DSL ("examples":http://github.com/jbe/sidekick/blob/master/lib/template).
|
18
|
+
* Easy to extend
|
19
|
+
* Compiles many languages, thanks to "Tilt":http://github.com/rtomayko/tilt.
|
20
|
+
* Powered by "EventMachine":http://github.com/eventmachine/eventmachine
|
21
|
+
* Short "core library":http://github.com/jbe/sidekick/blob/master/lib/sidekick.rb -- about 70 lines of code.
|
24
22
|
|
25
23
|
h2. Basic usage
|
26
24
|
|
27
25
|
Install with @gem install sidekick@ and invoke using the @sidekick@ command in your project folder. If you do not have a @.sidekick@ file, you will be offered a template.
|
28
26
|
|
29
|
-
|
30
|
-
|
31
|
-
|@watch(glob) { ... }@|run on file changes matching @glob@. Globs like "Dir[]":http://ruby-doc.org/core/classes/Dir.html#M002323. |
|
32
|
-
|@every(duration) { ... }@|run every @duration@ seconds|
|
33
|
-
|
34
|
-
h3. Currently available helpers:
|
35
|
-
|
36
|
-
|@sh(cmd)@|run shell command, printing and returning output|
|
37
|
-
|@log(str)@|log events to @STDOUT@.|
|
38
|
-
|@notify(message, title='sidekick')@|notify user via growl, libnotify etc.|
|
39
|
-
|@auto_compile(source_glob, target_path)@|compile on file changes using tilt (language automatically detected -- see example usage in template, and tilt documentation)|
|
40
|
-
|@restart_passenger@|restart passenger based environments by touching tmp/restart.txt|
|
41
|
-
|
42
|
-
Note how some helpers, like @auto_compile@ set up both triggers and actions for you.
|
27
|
+
Read the source to see all available "triggers":http://github.com/jbe/sidekick/blob/master/lib/sidekick/triggers.rb and "helpers":http://github.com/jbe/sidekick/blob/master/lib/sidekick/helpers.rb.
|
43
28
|
|
44
29
|
h2. Writing extensions
|
45
30
|
|
@@ -57,72 +42,18 @@ To add more helpers, simply add methods to @Sidekick::Helpers@, like this:
|
|
57
42
|
</code>
|
58
43
|
</pre>
|
59
44
|
|
60
|
-
They will be available to other helpers and to @.sidekick@ files.
|
45
|
+
They will be available to other helpers and to @.sidekick@ files. When adding a group of methods it may be cleaner to write a module under @Sidekick::Helpers@, and then including it.
|
61
46
|
|
62
47
|
|
63
48
|
h3. Writing new triggers
|
64
49
|
|
65
|
-
|
66
|
-
|
67
|
-
<pre>
|
68
|
-
<code lang='ruby'>
|
69
|
-
|
70
|
-
Sidekick::Triggers.register(:never) {|callback| }
|
71
|
-
# available in .sidekick like:
|
72
|
-
# never { puts 'nobody listens to me' }
|
73
|
-
|
74
|
-
Sidekick::Triggers.register(:on_startup) {|callback| callback.call }
|
75
|
-
# available like:
|
76
|
-
# on_startup { puts 'better to do this in the main scope than here' }
|
77
|
-
|
78
|
-
Sidekick::Triggers.register(:every) do |callback, duration|
|
79
|
-
timeshare(duration) do
|
80
|
-
callback.call
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
</code>
|
85
|
-
</pre>
|
86
|
-
|
87
|
-
The last example is the internal implementation of the @every@ trigger seen earlier, which calls the block periodically. @callback@ is the block given to the trigger in the @.sidekick@ file. @timeshare@ is a special method provided by Sidekick to all extensions, to register the supplied block to be called every @duration@ seconds. This is useful for polling something without blocking or doing something out of this world.
|
88
|
-
|
89
|
-
Now, here is the last example written as a class:
|
90
|
-
|
91
|
-
<pre>
|
92
|
-
<code lang='ruby'>
|
93
|
-
|
94
|
-
class Sidekick::Triggers::Every
|
95
|
-
|
96
|
-
def initialize(callback, duration)
|
97
|
-
@callback = callback
|
98
|
-
@duration = duration
|
99
|
-
end
|
100
|
-
|
101
|
-
def poll
|
102
|
-
@callback.call
|
103
|
-
end
|
104
|
-
|
105
|
-
def poll_freq
|
106
|
-
@duration
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
Sidekick::Triggers.register_class(:watch, Watch)
|
111
|
-
|
112
|
-
</code>
|
113
|
-
</pre>
|
114
|
-
|
115
|
-
The @poll@ and @poll_freq@ methods are optional. @poll@ functions like the callback block in the previous example, while @poll_freq@ functions like the @duration@ argument, specifying how often to call @poll@. Only integers (whole seconds) are accepted. Finally, notice the last statement, which registers the class.
|
116
|
-
|
117
|
-
h2. Fun facts
|
118
|
-
|
119
|
-
The main code chunk of Sidekick is just under 100 lines, including documentation, excluding the default triggers and helpers.
|
50
|
+
Have a look at the "existing triggers":http://github.com/jbe/sidekick/blob/master/lib/sidekick/triggers.rb, and you will get the idea. Basically, you define new triggers by calling @Sidekick::Triggers.register(:trigger_name) { .. }@, and hooking into EventMachine the same way as in @EM.run { .. }@.
|
120
51
|
|
121
52
|
You can keep your extensions in the @.sidekick@ file itself, or package them in gems, or (better) ask me to merge them into the main repository.
|
122
53
|
|
123
|
-
Similar projects:
|
54
|
+
h3. Similar projects:
|
124
55
|
|
125
|
-
* "Guard":http://github.com/guard/guard
|
56
|
+
* "Guard":http://github.com/guard/guard
|
126
57
|
|
127
58
|
|
128
59
|
h3. Copyright
|
data/Rakefile
CHANGED
@@ -6,11 +6,13 @@ begin
|
|
6
6
|
Jeweler::Tasks.new do |gem|
|
7
7
|
gem.name = "sidekick"
|
8
8
|
gem.summary = %Q{Automatically run common development tasks on events, as defined by a local .sidekick file.}
|
9
|
-
gem.description = %Q{Automatically run common development tasks on events, as defined by a local .sidekick file. Easy, powerful dsl
|
9
|
+
gem.description = %Q{Automatically run common development tasks on events, as defined by a local .sidekick file. Easy, powerful dsl including useful pre-defined triggers and helper methods for common tasks. Powered by EventMachine and easy to extend.}
|
10
10
|
gem.email = "post@jostein.be"
|
11
11
|
gem.homepage = "http://github.com/jbe/sidekick"
|
12
12
|
gem.authors = ["Jostein Berre Eliassen,"]
|
13
13
|
gem.add_dependency "tilt", ">= 1"
|
14
|
+
gem.add_dependency "eventmachine", ">= 0"
|
15
|
+
gem.add_dependency "em-dir-watcher", ">= 0"
|
14
16
|
end
|
15
17
|
Jeweler::GemcutterTasks.new
|
16
18
|
rescue LoadError
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.0
|
data/lib/sidekick.rb
CHANGED
@@ -1,102 +1,68 @@
|
|
1
1
|
require 'fileutils'
|
2
|
+
require 'eventmachine'
|
2
3
|
|
3
4
|
module Sidekick
|
4
5
|
|
5
|
-
|
6
|
-
# evaluates the .sidekick config file within
|
7
|
-
# its own scope
|
8
|
-
def self.run!(conf_path='.sidekick')
|
9
|
-
unless File.exists?(conf_path)
|
10
|
-
puts 'Generate new sidekick file? (Y/n)'
|
11
|
-
unless gets =~ /^N|n/ # 1.8 and 1.9 compatibility
|
12
|
-
FileUtils.cp(File.expand_path('../template', __FILE__), conf_path)
|
13
|
-
else
|
14
|
-
exit
|
15
|
-
end
|
16
|
-
end
|
17
|
-
Context.new(conf_path)
|
18
|
-
Triggers.enter_loop
|
19
|
-
end
|
20
|
-
|
21
|
-
|
22
|
-
# A new Context is used to run the .sidekick
|
23
|
-
# config file. It simply extends Module.
|
24
|
-
class Context < ::Module
|
25
|
-
def initialize(conf_path)
|
26
|
-
super()
|
27
|
-
extend MethodProxy
|
28
|
-
extend Helpers
|
29
|
-
code = open(conf_path) { |f| f.read }
|
30
|
-
module_eval(code, conf_path)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
# New contexts also extend MethodProxy, so that they
|
35
|
-
# can forward method calls to the registered sidekicks.
|
36
|
-
module MethodProxy
|
6
|
+
module Triggers
|
37
7
|
@@triggers = {}
|
38
8
|
|
39
|
-
|
40
|
-
def self.register(name, block)
|
9
|
+
def self.register(name, &block)
|
41
10
|
@@triggers[name] = block
|
42
11
|
end
|
43
12
|
|
13
|
+
def self.log(str) # used by triggers
|
14
|
+
puts str
|
15
|
+
end
|
16
|
+
|
44
17
|
def method_missing(name, *args, &blk)
|
45
|
-
|
46
|
-
@@triggers[name].call(blk, *args)
|
47
|
-
else
|
48
|
-
super
|
49
|
-
end
|
18
|
+
@@triggers[name] ?
|
19
|
+
@@triggers[name].call(blk, *args) : super
|
50
20
|
end
|
51
21
|
|
52
22
|
def respond_to?(method)
|
53
23
|
super || !!@@triggers[method]
|
54
24
|
end
|
25
|
+
|
55
26
|
end
|
56
27
|
|
57
|
-
#
|
58
|
-
|
59
|
-
|
60
|
-
@@timeshare_callbacks = []
|
61
|
-
@@timeshare_frequencies = []
|
62
|
-
|
63
|
-
class << self
|
64
|
-
|
65
|
-
# registers a sidekick available to .sidekick files
|
66
|
-
def register(name, &block)
|
67
|
-
MethodProxy.register(name, block)
|
68
|
-
end
|
69
|
-
|
70
|
-
# registers a callback for timesharing between
|
71
|
-
# active sidekicks
|
72
|
-
def timeshare(freq=1, &callback)
|
73
|
-
@@timeshare_callbacks << callback
|
74
|
-
@@timeshare_frequencies << freq
|
75
|
-
end
|
76
|
-
|
77
|
-
# begins the timesharing loop
|
78
|
-
def enter_loop
|
79
|
-
Signal.trap :INT do
|
80
|
-
exit
|
81
|
-
end
|
82
|
-
|
83
|
-
0.upto(1.0/0) do |n|
|
84
|
-
0.upto(@@timeshare_callbacks.size - 1) do |i|
|
85
|
-
if n % @@timeshare_frequencies[i] == 0
|
86
|
-
@@timeshare_callbacks[i].call(n)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
sleep 1
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def log(str)
|
94
|
-
puts str
|
95
|
-
end
|
28
|
+
# default library
|
29
|
+
require 'sidekick/triggers'
|
30
|
+
require 'sidekick/helpers'
|
96
31
|
|
32
|
+
# context in which to evaluate .sidekick file
|
33
|
+
Context = Module.new
|
34
|
+
Context.extend Triggers
|
35
|
+
Context.extend Helpers
|
36
|
+
|
37
|
+
|
38
|
+
def self.ensure_config_exists(path)
|
39
|
+
unless File.exists?(path)
|
40
|
+
puts 'Generate new sidekick file? (Y/n)'
|
41
|
+
gets =~ /^N|n/ ?
|
42
|
+
FileUtils.cp(File.expand_path('../template',
|
43
|
+
__FILE__), path) : exit
|
97
44
|
end
|
98
45
|
end
|
99
|
-
end
|
100
46
|
|
101
|
-
|
102
|
-
|
47
|
+
# reads and applies the .sidekick file, and begins
|
48
|
+
# the event loop.
|
49
|
+
def self.run!(path='.sidekick')
|
50
|
+
|
51
|
+
ensure_config_exists(path)
|
52
|
+
|
53
|
+
Signal.trap(:INT) { ::Sidekick.stop }
|
54
|
+
|
55
|
+
EventMachine.run do
|
56
|
+
Context.module_eval(
|
57
|
+
open(path) {|f| f.read }, path )
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# stops Sidekick gracefully
|
62
|
+
def self.stop(msg=false)
|
63
|
+
EventMachine.stop
|
64
|
+
puts
|
65
|
+
puts msg if msg
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
data/lib/sidekick/helpers.rb
CHANGED
@@ -7,53 +7,33 @@ require 'tilt'
|
|
7
7
|
|
8
8
|
module Sidekick::Helpers
|
9
9
|
|
10
|
-
|
11
|
-
# :linux, :darwin, :other
|
12
|
-
def platform
|
13
|
-
[:linux, :darwin].each do |plf|
|
14
|
-
return plf if Config::CONFIG['target_os'] =~ /#{plf}/i
|
15
|
-
end; :other
|
16
|
-
end
|
17
|
-
|
18
|
-
def running?(plf)
|
19
|
-
plf == platform
|
20
|
-
end
|
21
|
-
|
22
|
-
def gem_load?(gemname)
|
23
|
-
@installed ||= begin
|
24
|
-
require gemname
|
25
|
-
true
|
26
|
-
rescue LoadError
|
27
|
-
puts "Please install the #{gemname} gem to enable all functions."
|
28
|
-
false
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
10
|
+
# system
|
32
11
|
|
12
|
+
require 'sidekick/helpers/util'
|
33
13
|
include Util
|
34
|
-
extend Util
|
35
14
|
|
36
|
-
|
37
|
-
|
38
|
-
def self.show(message, title='Sidekick')
|
39
|
-
if running?(:linux) and gem_load?('libnotify')
|
40
|
-
Libnotify.show :body => message, :summary => title
|
41
|
-
elsif running?(:darwin) and gem_load?('growl')
|
42
|
-
Growl.notify message, :title => title, :name => 'Sidekick'
|
43
|
-
else
|
44
|
-
puts "Notification: #{title} #{message}"
|
45
|
-
end
|
46
|
-
end
|
15
|
+
def log(str)
|
16
|
+
puts ' -> ' + str
|
47
17
|
end
|
48
18
|
|
19
|
+
def stop(*prms)
|
20
|
+
Sidekick.stop(*prms)
|
21
|
+
end
|
49
22
|
|
23
|
+
# notifications
|
50
24
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
25
|
+
def notify(message, title='Sidekick')
|
26
|
+
|
27
|
+
gems = {:linux => 'libnotify', :darwin => 'growl'}
|
54
28
|
|
55
|
-
|
56
|
-
|
29
|
+
stop('Notifications not supported.') unless platform_load?(
|
30
|
+
gems, 'notifications')
|
31
|
+
case platform
|
32
|
+
when :linux
|
33
|
+
Libnotify.show :body => message, :summary => title
|
34
|
+
when :darwin
|
35
|
+
Growl.notify message, :title => title, :name => 'Sidekick'
|
36
|
+
end
|
57
37
|
end
|
58
38
|
|
59
39
|
def sh(cmd)
|
@@ -62,36 +42,30 @@ module Sidekick::Helpers
|
|
62
42
|
result
|
63
43
|
end
|
64
44
|
|
65
|
-
|
66
|
-
|
67
45
|
def restart_passenger
|
68
46
|
FileUtils.touch './tmp/restart.txt'
|
69
47
|
log 'restarted passenger'
|
70
48
|
end
|
71
49
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
50
|
# watches for changes matching the source glob,
|
76
51
|
# compiles using the tilt gem, and saves to
|
77
52
|
# target. Target is interpolated for :name
|
78
53
|
def auto_compile(source, target)
|
79
54
|
watch(source) do |files|
|
80
55
|
files.each do |file|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
56
|
+
if File.exists?(file)
|
57
|
+
begin
|
58
|
+
t = target.gsub(':name', File.basename(file, '.*'))
|
59
|
+
File.open(t, 'w') do |f|
|
60
|
+
f.write(Tilt.new(file).render)
|
61
|
+
end
|
62
|
+
log "render #{file} => #{t}"
|
63
|
+
rescue Exception => e
|
64
|
+
notify "Error in #{file}:\n#{e}"
|
85
65
|
end
|
86
|
-
log "rendered #{file} => #{target}"
|
87
|
-
rescue Exception => e
|
88
|
-
notify "Error in #{file}:\n#{e}"
|
89
66
|
end
|
90
67
|
end
|
91
68
|
end
|
92
69
|
end
|
93
70
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
71
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
module Util
|
6
|
+
# :linux, :darwin, :other
|
7
|
+
def platform
|
8
|
+
[:linux, :darwin].each do |plf|
|
9
|
+
return plf if Config::CONFIG['target_os'] =~ /#{plf}/i
|
10
|
+
end; :other
|
11
|
+
end
|
12
|
+
|
13
|
+
def gem_load?(gemname, function='full')
|
14
|
+
@installed ||= begin
|
15
|
+
require gemname
|
16
|
+
true
|
17
|
+
rescue LoadError
|
18
|
+
"Please gem install #{gemname} for #{function} support."
|
19
|
+
::Sidekick.stop
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def platform_load?(gems, function='full')
|
24
|
+
gem_load?(gems[platform], function)
|
25
|
+
end
|
26
|
+
end
|
data/lib/sidekick/triggers.rb
CHANGED
@@ -1,25 +1,26 @@
|
|
1
1
|
|
2
2
|
|
3
|
-
|
3
|
+
require 'em-dir-watcher'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
def self.register_class(keyword, kls)
|
8
|
-
register(keyword) do |*prms|
|
9
|
-
o = kls.new(*prms)
|
10
|
-
freq = o.respond_to?(:poll_freq) ? o.poll_freq : 1
|
11
|
-
timeshare(freq) { o.poll } if o.respond_to? :poll
|
12
|
-
end
|
13
|
-
end
|
5
|
+
|
6
|
+
module Sidekick::Triggers
|
14
7
|
|
15
8
|
# default triggers
|
16
9
|
|
17
|
-
|
10
|
+
register :watch do |callback, glob|
|
11
|
+
EMDirWatcher.watch(
|
12
|
+
File.expand_path('.'),
|
13
|
+
:include_only => [glob],
|
14
|
+
:grace_period => 0.2
|
15
|
+
) do |paths|
|
16
|
+
log "watch #{paths.inspect}"
|
17
|
+
callback.call(paths)
|
18
|
+
end
|
19
|
+
end
|
18
20
|
|
19
|
-
register_class(:watch, Watch)
|
20
|
-
|
21
21
|
register :every do |callback, duration|
|
22
|
-
|
22
|
+
EventMachine::PeriodicTimer.new(duration) do
|
23
|
+
log "every #{duration} seconds"
|
23
24
|
callback.call
|
24
25
|
end
|
25
26
|
end
|
data/lib/template
CHANGED
data/sidekick.gemspec
CHANGED
@@ -5,13 +5,13 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{sidekick}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.5.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jostein Berre Eliassen,"]
|
12
12
|
s.date = %q{2010-10-26}
|
13
13
|
s.default_executable = %q{sidekick}
|
14
|
-
s.description = %q{Automatically run common development tasks on events, as defined by a local .sidekick file. Easy, powerful dsl
|
14
|
+
s.description = %q{Automatically run common development tasks on events, as defined by a local .sidekick file. Easy, powerful dsl including useful pre-defined triggers and helper methods for common tasks. Powered by EventMachine and easy to extend.}
|
15
15
|
s.email = %q{post@jostein.be}
|
16
16
|
s.executables = ["sidekick"]
|
17
17
|
s.extra_rdoc_files = [
|
@@ -29,8 +29,8 @@ Gem::Specification.new do |s|
|
|
29
29
|
"bin/sidekick",
|
30
30
|
"lib/sidekick.rb",
|
31
31
|
"lib/sidekick/helpers.rb",
|
32
|
+
"lib/sidekick/helpers/util.rb",
|
32
33
|
"lib/sidekick/triggers.rb",
|
33
|
-
"lib/sidekick/triggers/watch.rb",
|
34
34
|
"lib/template",
|
35
35
|
"sidekick.gemspec",
|
36
36
|
"test/fixtures/page.haml",
|
@@ -55,11 +55,17 @@ Gem::Specification.new do |s|
|
|
55
55
|
|
56
56
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
57
57
|
s.add_runtime_dependency(%q<tilt>, [">= 1"])
|
58
|
+
s.add_runtime_dependency(%q<eventmachine>, [">= 0"])
|
59
|
+
s.add_runtime_dependency(%q<em-dir-watcher>, [">= 0"])
|
58
60
|
else
|
59
61
|
s.add_dependency(%q<tilt>, [">= 1"])
|
62
|
+
s.add_dependency(%q<eventmachine>, [">= 0"])
|
63
|
+
s.add_dependency(%q<em-dir-watcher>, [">= 0"])
|
60
64
|
end
|
61
65
|
else
|
62
66
|
s.add_dependency(%q<tilt>, [">= 1"])
|
67
|
+
s.add_dependency(%q<eventmachine>, [">= 0"])
|
68
|
+
s.add_dependency(%q<em-dir-watcher>, [">= 0"])
|
63
69
|
end
|
64
70
|
end
|
65
71
|
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 5
|
8
|
+
- 0
|
9
|
+
version: 0.5.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Jostein Berre Eliassen,
|
@@ -30,7 +30,33 @@ dependencies:
|
|
30
30
|
version: "1"
|
31
31
|
type: :runtime
|
32
32
|
version_requirements: *id001
|
33
|
-
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: eventmachine
|
35
|
+
prerelease: false
|
36
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
version: "0"
|
44
|
+
type: :runtime
|
45
|
+
version_requirements: *id002
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: em-dir-watcher
|
48
|
+
prerelease: false
|
49
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
segments:
|
55
|
+
- 0
|
56
|
+
version: "0"
|
57
|
+
type: :runtime
|
58
|
+
version_requirements: *id003
|
59
|
+
description: Automatically run common development tasks on events, as defined by a local .sidekick file. Easy, powerful dsl including useful pre-defined triggers and helper methods for common tasks. Powered by EventMachine and easy to extend.
|
34
60
|
email: post@jostein.be
|
35
61
|
executables:
|
36
62
|
- sidekick
|
@@ -50,8 +76,8 @@ files:
|
|
50
76
|
- bin/sidekick
|
51
77
|
- lib/sidekick.rb
|
52
78
|
- lib/sidekick/helpers.rb
|
79
|
+
- lib/sidekick/helpers/util.rb
|
53
80
|
- lib/sidekick/triggers.rb
|
54
|
-
- lib/sidekick/triggers/watch.rb
|
55
81
|
- lib/template
|
56
82
|
- sidekick.gemspec
|
57
83
|
- test/fixtures/page.haml
|
@@ -1,55 +0,0 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
module Sidekick::Triggers::Watch
|
4
|
-
|
5
|
-
def self.new(*args)
|
6
|
-
|
7
|
-
name, adapter_class = {
|
8
|
-
:linux => [nil, Polling], # Ready to implement fs-event
|
9
|
-
:darwin => [nil, Polling], # and libnotify. Polling seems
|
10
|
-
:other => [nil, Polling] # to work perfectly though.
|
11
|
-
}[::Sidekick::Helpers.platform]
|
12
|
-
|
13
|
-
unless name.nil?
|
14
|
-
adapter_class = Polling unless Sidekick::Helpers.load_gem?(name)
|
15
|
-
end
|
16
|
-
adapter_class.new(*args)
|
17
|
-
end
|
18
|
-
|
19
|
-
class Polling # todo: check for deletion
|
20
|
-
|
21
|
-
def initialize(callback, glob, ignore_first=false)
|
22
|
-
::Sidekick::Triggers.log "polling #{glob} for file changes.."
|
23
|
-
@path = glob
|
24
|
-
@file_timestamps = {}
|
25
|
-
@callback = callback
|
26
|
-
read_changes if ignore_first # prebuild cache
|
27
|
-
end
|
28
|
-
|
29
|
-
def poll
|
30
|
-
if changed?
|
31
|
-
::Sidekick::Triggers.log "modified #{@changes.inspect}"
|
32
|
-
@callback.call(@changes)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def changed?
|
39
|
-
read_changes
|
40
|
-
!@changes.empty?
|
41
|
-
end
|
42
|
-
|
43
|
-
def read_changes
|
44
|
-
@changes = []
|
45
|
-
Dir[@path].each do |path|
|
46
|
-
mtime = File.new('./' + path).mtime
|
47
|
-
unless @file_timestamps[path] == mtime
|
48
|
-
@changes << path
|
49
|
-
@file_timestamps[path] = mtime
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|