sidekick 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -18,5 +18,6 @@ coverage
18
18
  rdoc
19
19
  pkg
20
20
  test/output
21
+ sidekick.gemspec
21
22
 
22
23
  ## PROJECT::SPECIFIC
@@ -0,0 +1,3 @@
1
+ [submodule "website"]
2
+ path = website
3
+ url = git@github.com:jbe/sidekick.git
@@ -1,30 +1,41 @@
1
1
  h1. Sidekick
2
2
 
3
+ "Sidekick":http://ibuildlegobricks.tumblr.com/post/1398895151/automate-common-tasks-with-sidekick is a command line tool to automatically trigger actions on certain events, as defined per project, in a local @.sidekick@ file in your project folder:
3
4
 
4
- "Sidekick":http://ibuildlegobricks.tumblr.com/post/1398895151/automate-common-tasks-with-sidekick is a command line tool to automatically trigger actions on certain events, as defined per project, in a local @.sidekick@ file in your project folder.
5
+ <pre><code>
6
+ watch('**/*.rb') { restart_passenger }
5
7
 
6
- h3. Use cases
8
+ auto_compile 'assets/*.sass', 'public/:name.css'
9
+
10
+ every(10) { notify sh 'fortune' }
11
+ </pre></code>
12
+
13
+ h3. Sample use cases
7
14
 
8
15
  * Restart server when code is changed
9
- * Compile Sass and CoffeeScript templates when they are updated
16
+ * Auto-compile Sass or CoffeeScript templates (and many other languages)
10
17
  * Periodically run commands
11
- * Continuous testing, with notifications and flexible hooks
12
-
13
- You typically run Sidekick in the background to automate this while coding.
18
+ * Continuous testing, notifications, hooks, you name it
14
19
 
15
20
  h3. Features
16
21
 
17
- * Simple and powerful DSL ("examples":http://github.com/jbe/sidekick/blob/master/lib/template).
22
+ * Simple and powerful DSL
18
23
  * Easy to extend
19
- * Compiles many languages, thanks to "Tilt":http://github.com/rtomayko/tilt.
24
+ * Compiles many formats, thanks to "Tilt":http://github.com/rtomayko/tilt.
20
25
  * 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.
26
+ * The core is about 60 lines of code
27
+
28
+ You should "read the annotated source code":http://jbe.github.com/sidekick/.
22
29
 
23
30
  h2. Basic usage
24
31
 
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.
32
+ Install with @gem install sidekick@ and invoke the @sidekick@ command in your project folder. If you do not have a @.sidekick@ file, you will be offered a template.
33
+
34
+ For now, look to the source code to see all available
26
35
 
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.
36
+ * "triggers":http://jbe.github.com/sidekick/triggers.html
37
+
38
+ * "helpers":http://jbe.github.com/sidekick/helpers.html
28
39
 
29
40
  h2. Writing extensions
30
41
 
@@ -47,15 +58,10 @@ They will be available to other helpers and to @.sidekick@ files. When adding a
47
58
 
48
59
  h3. Writing new triggers
49
60
 
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 { .. }@.
61
+ Have a look at the "existing triggers":http://jbe.github.com/sidekick/triggers.html, 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 { .. }@ from there.
51
62
 
52
63
  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.
53
64
 
54
- h3. Similar projects:
55
-
56
- * "Guard":http://github.com/guard/guard
57
-
58
-
59
65
  h3. Copyright
60
66
 
61
67
  Copyright (c) 2010 Jostein Berre Eliassen. See LICENSE for details.
data/Rakefile CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'rake'
3
+ require 'rake/clean'
3
4
 
4
5
  begin
5
6
  require 'jeweler'
@@ -19,30 +20,8 @@ rescue LoadError
19
20
  puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
20
21
  end
21
22
 
22
- require 'rake/testtask'
23
- Rake::TestTask.new(:test) do |test|
24
- test.libs << 'lib' << 'test'
25
- test.pattern = 'test/**/test_*.rb'
26
- test.verbose = true
27
- end
28
-
29
- begin
30
- require 'rcov/rcovtask'
31
- Rcov::RcovTask.new do |test|
32
- test.libs << 'test'
33
- test.pattern = 'test/**/test_*.rb'
34
- test.verbose = true
35
- end
36
- rescue LoadError
37
- task :rcov do
38
- abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
39
- end
40
- end
41
-
42
- task :test => :check_dependencies
43
-
44
- task :default => :test
45
23
 
24
+ =begin
46
25
  require 'rake/rdoctask'
47
26
  Rake::RDocTask.new do |rdoc|
48
27
  version = File.exist?('VERSION') ? File.read('VERSION') : ""
@@ -52,3 +31,23 @@ Rake::RDocTask.new do |rdoc|
52
31
  rdoc.rdoc_files.include('README*')
53
32
  rdoc.rdoc_files.include('lib/**/*.rb')
54
33
  end
34
+ =end
35
+
36
+ require 'rocco/tasks'
37
+ Rocco::make 'annotated/'
38
+
39
+ desc 'Build docco'
40
+ task :docs => [:rocco, 'website/index.html']
41
+ directory 'annotated/'
42
+
43
+ # Make index.html a copy of rocco.html
44
+ file 'website/index.html' => 'website/sidekick.html' do |f|
45
+ cp 'website/sidekick.html', 'website/index.html', :preserve => true
46
+ end
47
+
48
+ CLEAN.include 'website/index.html'
49
+ task :doc => :docs
50
+
51
+ # GITHUB PAGES ===============================================================
52
+
53
+
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.1
1
+ 0.6.0
@@ -0,0 +1,143 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="content-type" content="text/html;charset=utf-8">
5
+ <title>helpers.rb</title>
6
+ <link rel="stylesheet" href="http://jashkenas.github.com/docco/resources/docco.css">
7
+ </head>
8
+ <body>
9
+ <div id='container'>
10
+ <div id="background"></div>
11
+ <div id="jump_to">
12
+ Jump To &hellip;
13
+ <div id="jump_wrapper">
14
+ <div id="jump_page">
15
+ <a class="source" href="sidekick.html">sidekick.rb</a>
16
+ <a class="source" href="helpers.html">helpers.rb</a>
17
+ <a class="source" href="util.html">util.rb</a>
18
+ <a class="source" href="triggers.html">triggers.rb</a>
19
+ </div>
20
+ </div>
21
+ </div>
22
+ <table cellspacing=0 cellpadding=0>
23
+ <thead>
24
+ <tr>
25
+ <th class=docs><h1>helpers.rb</h1></th>
26
+ <th class=code></th>
27
+ </tr>
28
+ </thead>
29
+ <tbody>
30
+ <tr id='section-1'>
31
+ <td class=docs>
32
+ <div class="octowrap">
33
+ <a class="octothorpe" href="#section-1">#</a>
34
+ </div>
35
+
36
+ </td>
37
+ <td class=code>
38
+ <div class='highlight'><pre><span class="nb">require</span> <span class="s1">&#39;fileutils&#39;</span>
39
+ <span class="nb">require</span> <span class="s1">&#39;rbconfig&#39;</span>
40
+ <span class="nb">require</span> <span class="s1">&#39;tilt&#39;</span></pre></div>
41
+ </td>
42
+ </tr>
43
+ <tr id='section-2'>
44
+ <td class=docs>
45
+ <div class="octowrap">
46
+ <a class="octothorpe" href="#section-2">#</a>
47
+ </div>
48
+ <p> default helpers</p>
49
+ </td>
50
+ <td class=code>
51
+ <div class='highlight'><pre><span class="k">module</span> <span class="nn">Sidekick::Helpers</span></pre></div>
52
+ </td>
53
+ </tr>
54
+ <tr id='section-3'>
55
+ <td class=docs>
56
+ <div class="octowrap">
57
+ <a class="octothorpe" href="#section-3">#</a>
58
+ </div>
59
+ <p> system</p>
60
+ </td>
61
+ <td class=code>
62
+ <div class='highlight'><pre> <span class="nb">require</span> <span class="s1">&#39;sidekick/helpers/util&#39;</span>
63
+ <span class="kp">include</span> <span class="no">Util</span>
64
+
65
+ <span class="k">def</span> <span class="nf">log</span><span class="p">(</span><span class="n">str</span><span class="p">)</span>
66
+ <span class="nb">puts</span> <span class="s1">&#39; -&gt; &#39;</span> <span class="o">+</span> <span class="n">str</span>
67
+ <span class="k">end</span>
68
+
69
+ <span class="k">def</span> <span class="nf">stop</span><span class="p">(</span><span class="o">*</span><span class="n">prms</span><span class="p">)</span>
70
+ <span class="no">Sidekick</span><span class="o">.</span><span class="n">stop</span><span class="p">(</span><span class="o">*</span><span class="n">prms</span><span class="p">)</span>
71
+ <span class="k">end</span></pre></div>
72
+ </td>
73
+ </tr>
74
+ <tr id='section-4'>
75
+ <td class=docs>
76
+ <div class="octowrap">
77
+ <a class="octothorpe" href="#section-4">#</a>
78
+ </div>
79
+ <p> notifications</p>
80
+ </td>
81
+ <td class=code>
82
+ <div class='highlight'><pre> <span class="k">def</span> <span class="nf">notify</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="n">title</span><span class="o">=</span><span class="s1">&#39;Sidekick&#39;</span><span class="p">)</span>
83
+
84
+ <span class="n">gems</span> <span class="o">=</span> <span class="p">{</span><span class="ss">:linux</span> <span class="o">=&gt;</span> <span class="s1">&#39;libnotify&#39;</span><span class="p">,</span> <span class="ss">:darwin</span> <span class="o">=&gt;</span> <span class="s1">&#39;growl&#39;</span><span class="p">}</span>
85
+
86
+ <span class="n">stop</span><span class="p">(</span><span class="s1">&#39;Notifications not supported.&#39;</span><span class="p">)</span> <span class="k">unless</span> <span class="n">platform_load?</span><span class="p">(</span>
87
+ <span class="n">gems</span><span class="p">,</span> <span class="s1">&#39;notifications&#39;</span><span class="p">)</span>
88
+ <span class="k">case</span> <span class="n">platform</span>
89
+ <span class="k">when</span> <span class="ss">:linux</span>
90
+ <span class="no">Libnotify</span><span class="o">.</span><span class="n">show</span> <span class="ss">:body</span> <span class="o">=&gt;</span> <span class="n">message</span><span class="p">,</span> <span class="ss">:summary</span> <span class="o">=&gt;</span> <span class="n">title</span>
91
+ <span class="k">when</span> <span class="ss">:darwin</span>
92
+ <span class="no">Growl</span><span class="o">.</span><span class="n">notify</span> <span class="n">message</span><span class="p">,</span> <span class="ss">:title</span> <span class="o">=&gt;</span> <span class="n">title</span><span class="p">,</span> <span class="ss">:name</span> <span class="o">=&gt;</span> <span class="s1">&#39;Sidekick&#39;</span>
93
+ <span class="k">end</span>
94
+ <span class="k">end</span>
95
+
96
+ <span class="k">def</span> <span class="nf">sh</span><span class="p">(</span><span class="n">cmd</span><span class="p">)</span>
97
+ <span class="n">log</span> <span class="n">cmd</span>
98
+ <span class="nb">puts</span> <span class="n">result</span> <span class="o">=</span> <span class="sb">`</span><span class="si">#{</span><span class="n">cmd</span><span class="si">}</span><span class="sb">`</span>
99
+ <span class="n">result</span>
100
+ <span class="k">end</span>
101
+
102
+ <span class="k">def</span> <span class="nf">restart_passenger</span>
103
+ <span class="no">FileUtils</span><span class="o">.</span><span class="n">touch</span> <span class="s1">&#39;./tmp/restart.txt&#39;</span>
104
+ <span class="n">log</span> <span class="s1">&#39;restarted passenger&#39;</span>
105
+ <span class="k">end</span></pre></div>
106
+ </td>
107
+ </tr>
108
+ <tr id='section-5'>
109
+ <td class=docs>
110
+ <div class="octowrap">
111
+ <a class="octothorpe" href="#section-5">#</a>
112
+ </div>
113
+ <p> watches for changes matching the source glob,
114
+ compiles using the tilt gem, and saves to
115
+ target. Target is interpolated for :name</p>
116
+
117
+ </td>
118
+ <td class=code>
119
+ <div class='highlight'><pre> <span class="k">def</span> <span class="nf">auto_compile</span><span class="p">(</span><span class="n">source</span><span class="p">,</span> <span class="n">target</span><span class="p">)</span>
120
+ <span class="n">watch</span><span class="p">(</span><span class="n">source</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">files</span><span class="o">|</span>
121
+ <span class="n">files</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">file</span><span class="o">|</span>
122
+ <span class="k">if</span> <span class="no">File</span><span class="o">.</span><span class="n">exists?</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
123
+ <span class="k">begin</span>
124
+ <span class="n">t</span> <span class="o">=</span> <span class="n">target</span><span class="o">.</span><span class="n">gsub</span><span class="p">(</span><span class="s1">&#39;:name&#39;</span><span class="p">,</span> <span class="no">File</span><span class="o">.</span><span class="n">basename</span><span class="p">(</span><span class="n">file</span><span class="p">,</span> <span class="s1">&#39;.*&#39;</span><span class="p">))</span>
125
+ <span class="no">File</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">t</span><span class="p">,</span> <span class="s1">&#39;w&#39;</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">f</span><span class="o">|</span>
126
+ <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="no">Tilt</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">file</span><span class="p">)</span><span class="o">.</span><span class="n">render</span><span class="p">)</span>
127
+ <span class="k">end</span>
128
+ <span class="n">log</span> <span class="s2">&quot;render </span><span class="si">#{</span><span class="n">file</span><span class="si">}</span><span class="s2"> =&gt; </span><span class="si">#{</span><span class="n">t</span><span class="si">}</span><span class="s2">&quot;</span>
129
+ <span class="k">rescue</span> <span class="no">Exception</span> <span class="o">=&gt;</span> <span class="n">e</span>
130
+ <span class="n">notify</span> <span class="s2">&quot;Error in </span><span class="si">#{</span><span class="n">file</span><span class="si">}</span><span class="s2">:</span><span class="se">\n</span><span class="si">#{</span><span class="n">e</span><span class="si">}</span><span class="s2">&quot;</span>
131
+ <span class="n">log</span> <span class="s2">&quot;Error in </span><span class="si">#{</span><span class="n">file</span><span class="si">}</span><span class="s2">:</span><span class="se">\n</span><span class="si">#{</span><span class="n">e</span><span class="si">}</span><span class="s2">&quot;</span>
132
+ <span class="k">end</span>
133
+ <span class="k">end</span>
134
+ <span class="k">end</span>
135
+ <span class="k">end</span>
136
+ <span class="k">end</span>
137
+
138
+ <span class="k">end</span></pre></div>
139
+ </td>
140
+ </tr>
141
+ </table>
142
+ </div>
143
+ </body>
@@ -0,0 +1,155 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="content-type" content="text/html;charset=utf-8">
5
+ <title>sidekick.rb</title>
6
+ <link rel="stylesheet" href="http://jashkenas.github.com/docco/resources/docco.css">
7
+ </head>
8
+ <body>
9
+ <div id='container'>
10
+ <div id="background"></div>
11
+ <div id="jump_to">
12
+ Jump To &hellip;
13
+ <div id="jump_wrapper">
14
+ <div id="jump_page">
15
+ <a class="source" href="sidekick.html">sidekick.rb</a>
16
+ <a class="source" href="helpers.html">helpers.rb</a>
17
+ <a class="source" href="util.html">util.rb</a>
18
+ <a class="source" href="triggers.html">triggers.rb</a>
19
+ </div>
20
+ </div>
21
+ </div>
22
+ <table cellspacing=0 cellpadding=0>
23
+ <thead>
24
+ <tr>
25
+ <th class=docs><h1>sidekick.rb</h1></th>
26
+ <th class=code></th>
27
+ </tr>
28
+ </thead>
29
+ <tbody>
30
+ <tr id='section-1'>
31
+ <td class=docs>
32
+ <div class="octowrap">
33
+ <a class="octothorpe" href="#section-1">#</a>
34
+ </div>
35
+ <p> <em>Sidekick</em> is a simple event driven background assistant. Among other things, you can use it to automatically compile assets, test code, restart servers and so on &ndash; as prescribed per project, in a <code>.sidekick</code> file. It is powered by EventMachine and Tilt.</p>
36
+
37
+ <p> This is the annotated source code. See the <a href="http://github.com/jbe/sidekick#readme">README</a> too.</p>
38
+
39
+ <hr />
40
+
41
+ <p> Sidekick basically helps you do two things:</p>
42
+
43
+ <p> &mdash; <em>Define</em> named triggers, such as saying that <code>watch(glob)</code> means doing something when a file matching <code>glob</code> changes, or that <code>every(duration)</code> means doing something every <code>duration</code> seconds.</p>
44
+
45
+ <p> &mdash; <em>Use</em> the defined triggers with callbacks, such as <code>watch(**.rb) { notify 'Code change' }</code></p>
46
+ </td>
47
+ <td class=code>
48
+ <div class='highlight'><pre><span class="nb">require</span> <span class="s1">&#39;fileutils&#39;</span>
49
+ <span class="nb">require</span> <span class="s1">&#39;eventmachine&#39;</span>
50
+
51
+ <span class="k">module</span> <span class="nn">Sidekick</span></pre></div>
52
+ </td>
53
+ </tr>
54
+ <tr id='section-2'>
55
+ <td class=docs>
56
+ <div class="octowrap">
57
+ <a class="octothorpe" href="#section-2">#</a>
58
+ </div>
59
+ <p> This core functionality is provided by <code>Sidekick::Triggers</code>.</p>
60
+
61
+ <p> New triggers can be defined by calling <code>Sidekick::Triggers.register(:trigger_name) { ... }</code>.</p>
62
+
63
+ <p>Basically, the job of a trigger definition is to take the parameters and the block from a call in <code>.sidekick</code> and use it to hook into EventMachine in some way. &mdash; Just have a look at the <a href="http://github.com/jbe/sidekick/blob/master/lib/sidekick/triggers.rb">default trigger library</a>.</p>
64
+
65
+ <p> By using Ruby&rsquo;s <code>method_missing</code>, we can forward method calls to the registered trigger definitions. Any module can thereby extend the <code>Triggers</code> module in order to expose the defined triggers as if they were methods.</p>
66
+ </td>
67
+ <td class=code>
68
+ <div class='highlight'><pre> <span class="k">module</span> <span class="nn">Triggers</span>
69
+ <span class="vc">@@triggers</span> <span class="o">=</span> <span class="p">{}</span>
70
+
71
+ <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">register</span><span class="p">(</span><span class="nb">name</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span><span class="p">)</span>
72
+ <span class="vc">@@triggers</span><span class="o">[</span><span class="nb">name</span><span class="o">]</span> <span class="o">=</span> <span class="n">block</span>
73
+ <span class="k">end</span>
74
+
75
+ <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">log</span><span class="p">(</span><span class="n">str</span><span class="p">)</span> <span class="c1"># used by triggers</span>
76
+ <span class="nb">puts</span> <span class="n">str</span>
77
+ <span class="k">end</span>
78
+
79
+ <span class="k">def</span> <span class="nf">method_missing</span><span class="p">(</span><span class="nb">name</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">blk</span><span class="p">)</span>
80
+ <span class="vc">@@triggers</span><span class="o">[</span><span class="nb">name</span><span class="o">]</span> <span class="p">?</span>
81
+ <span class="vc">@@triggers</span><span class="o">[</span><span class="nb">name</span><span class="o">].</span><span class="n">call</span><span class="p">(</span><span class="n">blk</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">)</span> <span class="p">:</span> <span class="k">super</span>
82
+ <span class="k">end</span>
83
+
84
+ <span class="k">def</span> <span class="nf">respond_to?</span><span class="p">(</span><span class="nb">method</span><span class="p">)</span>
85
+ <span class="k">super</span> <span class="o">||</span> <span class="o">!!</span><span class="vc">@@triggers</span><span class="o">[</span><span class="nb">method</span><span class="o">]</span>
86
+ <span class="k">end</span>
87
+
88
+ <span class="k">end</span></pre></div>
89
+ </td>
90
+ </tr>
91
+ <tr id='section-3'>
92
+ <td class=docs>
93
+ <div class="octowrap">
94
+ <a class="octothorpe" href="#section-3">#</a>
95
+ </div>
96
+ <p> A default library of triggers and helpers is included..</p>
97
+ </td>
98
+ <td class=code>
99
+ <div class='highlight'><pre> <span class="nb">require</span> <span class="s1">&#39;sidekick/triggers&#39;</span>
100
+ <span class="nb">require</span> <span class="s1">&#39;sidekick/helpers&#39;</span></pre></div>
101
+ </td>
102
+ </tr>
103
+ <tr id='section-4'>
104
+ <td class=docs>
105
+ <div class="octowrap">
106
+ <a class="octothorpe" href="#section-4">#</a>
107
+ </div>
108
+ <p> The <code>.sidekick</code> file is evaluated in a <code>Sidekick::Context</code> module, which exposes DSL style methods by extending <code>Sidekick::Triggers</code> and <code>Sidekick::Helpers</code>.</p>
109
+ </td>
110
+ <td class=code>
111
+ <div class='highlight'><pre> <span class="no">Context</span> <span class="o">=</span> <span class="no">Module</span><span class="o">.</span><span class="n">new</span>
112
+ <span class="no">Context</span><span class="o">.</span><span class="n">extend</span> <span class="no">Triggers</span>
113
+ <span class="no">Context</span><span class="o">.</span><span class="n">extend</span> <span class="no">Helpers</span></pre></div>
114
+ </td>
115
+ </tr>
116
+ <tr id='section-5'>
117
+ <td class=docs>
118
+ <div class="octowrap">
119
+ <a class="octothorpe" href="#section-5">#</a>
120
+ </div>
121
+ <p> The <code>Sidekick.run!</code> method reads and applies the <code>.sidekick</code> file, wrapping the setup phase inside <code>EM.run { .. }</code>, and thus begins the event loop.</p>
122
+
123
+ </td>
124
+ <td class=code>
125
+ <div class='highlight'><pre> <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">run!</span><span class="p">(</span><span class="n">path</span><span class="o">=</span><span class="s1">&#39;.sidekick&#39;</span><span class="p">)</span>
126
+ <span class="n">ensure_config_exists</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
127
+
128
+ <span class="no">Signal</span><span class="o">.</span><span class="n">trap</span><span class="p">(</span><span class="ss">:INT</span><span class="p">)</span> <span class="p">{</span> <span class="n">stop</span> <span class="p">}</span>
129
+
130
+ <span class="no">EventMachine</span><span class="o">.</span><span class="n">run</span> <span class="k">do</span>
131
+ <span class="no">Context</span><span class="o">.</span><span class="n">module_eval</span><span class="p">(</span>
132
+ <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">)</span> <span class="p">{</span><span class="o">|</span><span class="n">f</span><span class="o">|</span> <span class="n">f</span><span class="o">.</span><span class="n">read</span> <span class="p">},</span> <span class="n">path</span> <span class="p">)</span>
133
+ <span class="k">end</span>
134
+ <span class="k">end</span>
135
+
136
+ <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">ensure_config_exists</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
137
+ <span class="k">unless</span> <span class="no">File</span><span class="o">.</span><span class="n">exists?</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
138
+ <span class="nb">puts</span> <span class="s1">&#39;Generate new sidekick file? (Y/n)&#39;</span>
139
+ <span class="nb">gets</span> <span class="o">=~</span> <span class="sr">/^N|n/</span> <span class="p">?</span> <span class="nb">exit</span> <span class="p">:</span>
140
+ <span class="no">FileUtils</span><span class="o">.</span><span class="n">cp</span><span class="p">(</span><span class="no">File</span><span class="o">.</span><span class="n">expand_path</span><span class="p">(</span><span class="s1">&#39;../template&#39;</span><span class="p">,</span>
141
+ <span class="bp">__FILE__</span><span class="p">),</span> <span class="n">path</span><span class="p">)</span>
142
+ <span class="k">end</span>
143
+ <span class="k">end</span>
144
+
145
+ <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">stop</span><span class="p">(</span><span class="n">msg</span><span class="o">=</span><span class="kp">false</span><span class="p">)</span>
146
+ <span class="no">EventMachine</span><span class="o">.</span><span class="n">stop</span>
147
+ <span class="nb">puts</span> <span class="s2">&quot;</span><span class="se">\n</span><span class="si">#{</span><span class="n">msg</span><span class="si">}</span><span class="s2">&quot;</span> <span class="k">if</span> <span class="n">msg</span>
148
+ <span class="k">end</span>
149
+
150
+ <span class="k">end</span></pre></div>
151
+ </td>
152
+ </tr>
153
+ </table>
154
+ </div>
155
+ </body>
@@ -0,0 +1,144 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="content-type" content="text/html;charset=utf-8">
5
+ <title>sidekick.rb</title>
6
+ <link rel="stylesheet" href="http://jashkenas.github.com/docco/resources/docco.css">
7
+ </head>
8
+ <body>
9
+ <div id='container'>
10
+ <div id="background"></div>
11
+ <table cellspacing=0 cellpadding=0>
12
+ <thead>
13
+ <tr>
14
+ <th class=docs><h1>sidekick.rb</h1></th>
15
+ <th class=code></th>
16
+ </tr>
17
+ </thead>
18
+ <tbody>
19
+ <tr id='section-1'>
20
+ <td class=docs>
21
+ <div class="octowrap">
22
+ <a class="octothorpe" href="#section-1">#</a>
23
+ </div>
24
+ <p> <em>Sidekick</em> is a simple event driven background assistant. Among other things, you can use it to automatically compile assets, test code, restart servers and so on &ndash; as prescribed per project, in a <code>.sidekick</code> file. It is powered by EventMachine and Tilt.</p>
25
+
26
+ <p> This is the annotated source code. See the <a href="http://github.com/jbe/sidekick#readme">README</a> too.</p>
27
+
28
+ <hr />
29
+
30
+ <p> Sidekick basically helps you do two things:</p>
31
+
32
+ <p> &mdash; <em>Define</em> named triggers, such as saying that <code>watch(glob)</code> means doing something when a file matching <code>glob</code> changes, or that <code>every(duration)</code> means doing something every <code>duration</code> seconds.</p>
33
+
34
+ <p> &mdash; <em>Use</em> the defined triggers with callbacks, such as <code>watch(**.rb) { notify 'Code change' }</code></p>
35
+ </td>
36
+ <td class=code>
37
+ <div class='highlight'><pre><span class="nb">require</span> <span class="s1">&#39;fileutils&#39;</span>
38
+ <span class="nb">require</span> <span class="s1">&#39;eventmachine&#39;</span>
39
+
40
+ <span class="k">module</span> <span class="nn">Sidekick</span></pre></div>
41
+ </td>
42
+ </tr>
43
+ <tr id='section-2'>
44
+ <td class=docs>
45
+ <div class="octowrap">
46
+ <a class="octothorpe" href="#section-2">#</a>
47
+ </div>
48
+ <p> This core functionality is provided by <code>Sidekick::Triggers</code>.</p>
49
+
50
+ <p> New triggers can be defined by calling <code>Sidekick::Triggers.register(:trigger_name) { ... }</code>.</p>
51
+
52
+ <p>Basically, the job of a trigger definition is to take the parameters and the block from a call in <code>.sidekick</code> and use it to hook into EventMachine in some way. &mdash; Just have a look at the <a href="http://github.com/jbe/sidekick/blob/master/lib/sidekick/triggers.rb">default trigger library</a>.</p>
53
+
54
+ <p> By using Ruby&rsquo;s <code>method_missing</code>, we can forward method calls to the registered trigger definitions. Any module can thereby extend the <code>Triggers</code> module in order to expose the defined triggers as if they were methods.</p>
55
+ </td>
56
+ <td class=code>
57
+ <div class='highlight'><pre> <span class="k">module</span> <span class="nn">Triggers</span>
58
+ <span class="vc">@@triggers</span> <span class="o">=</span> <span class="p">{}</span>
59
+
60
+ <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">register</span><span class="p">(</span><span class="nb">name</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">block</span><span class="p">)</span>
61
+ <span class="vc">@@triggers</span><span class="o">[</span><span class="nb">name</span><span class="o">]</span> <span class="o">=</span> <span class="n">block</span>
62
+ <span class="k">end</span>
63
+
64
+ <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">log</span><span class="p">(</span><span class="n">str</span><span class="p">)</span> <span class="c1"># used by triggers</span>
65
+ <span class="nb">puts</span> <span class="n">str</span>
66
+ <span class="k">end</span>
67
+
68
+ <span class="k">def</span> <span class="nf">method_missing</span><span class="p">(</span><span class="nb">name</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">blk</span><span class="p">)</span>
69
+ <span class="vc">@@triggers</span><span class="o">[</span><span class="nb">name</span><span class="o">]</span> <span class="p">?</span>
70
+ <span class="vc">@@triggers</span><span class="o">[</span><span class="nb">name</span><span class="o">].</span><span class="n">call</span><span class="p">(</span><span class="n">blk</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">)</span> <span class="p">:</span> <span class="k">super</span>
71
+ <span class="k">end</span>
72
+
73
+ <span class="k">def</span> <span class="nf">respond_to?</span><span class="p">(</span><span class="nb">method</span><span class="p">)</span>
74
+ <span class="k">super</span> <span class="o">||</span> <span class="o">!!</span><span class="vc">@@triggers</span><span class="o">[</span><span class="nb">method</span><span class="o">]</span>
75
+ <span class="k">end</span>
76
+
77
+ <span class="k">end</span></pre></div>
78
+ </td>
79
+ </tr>
80
+ <tr id='section-3'>
81
+ <td class=docs>
82
+ <div class="octowrap">
83
+ <a class="octothorpe" href="#section-3">#</a>
84
+ </div>
85
+ <p> A default library of triggers and helpers is included..</p>
86
+ </td>
87
+ <td class=code>
88
+ <div class='highlight'><pre> <span class="nb">require</span> <span class="s1">&#39;sidekick/triggers&#39;</span>
89
+ <span class="nb">require</span> <span class="s1">&#39;sidekick/helpers&#39;</span></pre></div>
90
+ </td>
91
+ </tr>
92
+ <tr id='section-4'>
93
+ <td class=docs>
94
+ <div class="octowrap">
95
+ <a class="octothorpe" href="#section-4">#</a>
96
+ </div>
97
+ <p> The <code>.sidekick</code> file is evaluated in a <code>Sidekick::Context</code> module, which exposes DSL style methods by extending <code>Sidekick::Triggers</code> and <code>Sidekick::Helpers</code>.</p>
98
+ </td>
99
+ <td class=code>
100
+ <div class='highlight'><pre> <span class="no">Context</span> <span class="o">=</span> <span class="no">Module</span><span class="o">.</span><span class="n">new</span>
101
+ <span class="no">Context</span><span class="o">.</span><span class="n">extend</span> <span class="no">Triggers</span>
102
+ <span class="no">Context</span><span class="o">.</span><span class="n">extend</span> <span class="no">Helpers</span></pre></div>
103
+ </td>
104
+ </tr>
105
+ <tr id='section-5'>
106
+ <td class=docs>
107
+ <div class="octowrap">
108
+ <a class="octothorpe" href="#section-5">#</a>
109
+ </div>
110
+ <p> The <code>Sidekick.run!</code> method reads and applies the <code>.sidekick</code> file, wrapping the setup phase inside <code>EM.run { .. }</code>, and thus begins the event loop.</p>
111
+
112
+ </td>
113
+ <td class=code>
114
+ <div class='highlight'><pre> <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">run!</span><span class="p">(</span><span class="n">path</span><span class="o">=</span><span class="s1">&#39;.sidekick&#39;</span><span class="p">)</span>
115
+ <span class="n">ensure_config_exists</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
116
+
117
+ <span class="no">Signal</span><span class="o">.</span><span class="n">trap</span><span class="p">(</span><span class="ss">:INT</span><span class="p">)</span> <span class="p">{</span> <span class="n">stop</span> <span class="p">}</span>
118
+
119
+ <span class="no">EventMachine</span><span class="o">.</span><span class="n">run</span> <span class="k">do</span>
120
+ <span class="no">Context</span><span class="o">.</span><span class="n">module_eval</span><span class="p">(</span>
121
+ <span class="nb">open</span><span class="p">(</span><span class="n">path</span><span class="p">)</span> <span class="p">{</span><span class="o">|</span><span class="n">f</span><span class="o">|</span> <span class="n">f</span><span class="o">.</span><span class="n">read</span> <span class="p">},</span> <span class="n">path</span> <span class="p">)</span>
122
+ <span class="k">end</span>
123
+ <span class="k">end</span>
124
+
125
+ <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">ensure_config_exists</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
126
+ <span class="k">unless</span> <span class="no">File</span><span class="o">.</span><span class="n">exists?</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
127
+ <span class="nb">puts</span> <span class="s1">&#39;Generate new sidekick file? (Y/n)&#39;</span>
128
+ <span class="nb">gets</span> <span class="o">=~</span> <span class="sr">/^N|n/</span> <span class="p">?</span> <span class="nb">exit</span> <span class="p">:</span>
129
+ <span class="no">FileUtils</span><span class="o">.</span><span class="n">cp</span><span class="p">(</span><span class="no">File</span><span class="o">.</span><span class="n">expand_path</span><span class="p">(</span><span class="s1">&#39;../template&#39;</span><span class="p">,</span>
130
+ <span class="bp">__FILE__</span><span class="p">),</span> <span class="n">path</span><span class="p">)</span>
131
+ <span class="k">end</span>
132
+ <span class="k">end</span>
133
+
134
+ <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">stop</span><span class="p">(</span><span class="n">msg</span><span class="o">=</span><span class="kp">false</span><span class="p">)</span>
135
+ <span class="no">EventMachine</span><span class="o">.</span><span class="n">stop</span>
136
+ <span class="nb">puts</span> <span class="s2">&quot;</span><span class="se">\n</span><span class="si">#{</span><span class="n">msg</span><span class="si">}</span><span class="s2">&quot;</span> <span class="k">if</span> <span class="n">msg</span>
137
+ <span class="k">end</span>
138
+
139
+ <span class="k">end</span></pre></div>
140
+ </td>
141
+ </tr>
142
+ </table>
143
+ </div>
144
+ </body>