sidekick 0.4.2 → 0.5.0
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.
- 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
|