spectator-emacs 0.1.0 → 0.2.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/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- spectator-emacs (0.1.0)
4
+ spectator-emacs (0.2.0)
5
5
  docopt
6
6
  open4
7
7
  rb-inotify (~> 0.8.8)
data/README.md CHANGED
@@ -54,6 +54,7 @@ You can customize various aspects of how spectator-emacs works:
54
54
  `enotify-failure-face`for failures, `enotify-warning-face` for
55
55
  success with pending examples)
56
56
  * The Enotify slot id to register for notifications
57
+ * The major mode used for the rspec output buffer
57
58
 
58
59
  An example `.spectator-emacs' file:
59
60
 
@@ -67,7 +68,9 @@ require 'spectator/emacs'
67
68
  :success => "success",
68
69
  :pending => "pending"
69
70
  },
70
- :slot_id => "project foobar"
71
+ # Use org-mode to display the report buffer
72
+ :report_buffer_mode => "org",
73
+ :slot_id => "project foobar",
71
74
  :notification_face => {
72
75
  :pending => :font_lock_warning_face,
73
76
  # see the docs for detail on Symbol#keyword
@@ -138,9 +141,8 @@ Put this in your .emacs:
138
141
 
139
142
  ```lisp
140
143
  (require 'enotify)
144
+ (require 'enotify-tdd)
141
145
  (enotify-minor-mode t)
142
- (add-to-list 'load-path "path/to/enotify-spectator-emacs")
143
- (require 'enotify-spectator-emacs)
144
146
  ```
145
147
 
146
148
  ## Copyright
data/Rakefile CHANGED
@@ -44,7 +44,7 @@ task :default => :spec
44
44
 
45
45
  desc "Run spectator-emacs"
46
46
  task :'spectator-emacs' do
47
- load "bin/spectator-emacs"
47
+ system "ruby", "-Ilib", "bin/spectator-emacs"
48
48
  end
49
49
 
50
50
  ## YARD stuff
@@ -0,0 +1,300 @@
1
+ ;;; enotify-spectator.el --- Enotify plugin for spectator-emacs (ruby TDD)
2
+
3
+ ;; Copyright (C) 2012 Alessandro Piras
4
+
5
+ ;; Author: Alessandro Piras <laynor@gmail.com>
6
+ ;; Keywords: convenience
7
+ ;; URL: http://www.github.com/laynor/spectator-emacs
8
+
9
+ ;; This file is part of spectator-emacs.
10
+
11
+ ;; This program is free software; you can redistribute it and/or modify
12
+ ;; it under the terms of the GNU General Public License as published by
13
+ ;; the Free Software Foundation, either version 3 of the License, or
14
+ ;; (at your option) any later version.
15
+
16
+ ;; This program is distributed in the hope that it will be useful,
17
+ ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
+ ;; GNU General Public License for more details.
20
+
21
+ ;; You should have received a copy of the GNU General Public License
22
+ ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
23
+
24
+ ;;; Commentary:
25
+
26
+ ;; This enotify plugin is meant to be used together with the
27
+ ;; spectator-emacs ruby gem.
28
+ ;;
29
+ ;; Installation: add this file to your load path and require it:
30
+ ;; (add-to-list 'load-path "path/to/enotify-spectator/")
31
+ ;; (require 'enotify-spectator)
32
+ ;;
33
+ ;; This plugin can take advantage of alert.el. If you want to enable
34
+ ;; alert.el alerts, customize `enotify-spectator-use-alert' and ensure
35
+ ;; alert.el is loaded before this file.
36
+
37
+ ;;; Code:
38
+
39
+ (require 'enotify)
40
+
41
+ (defgroup enotify-spectator nil
42
+ "Enotify plugin for spectator-emacs"
43
+ :group 'enotify)
44
+
45
+ (defcustom enotify-spectator-use-alert nil
46
+ "whether enotify-spectator should use alert.el"
47
+ :group 'enotify-spectator
48
+ :type 'boolean)
49
+
50
+ (defcustom enotify-spectator-alert-severity 'trivial
51
+ "severity for alert.el alerts"
52
+ :group 'enotify-spectator
53
+ :type '(choice (const :tag "Urgent" urgent)
54
+ (const :tag "High" high)
55
+ (const :tag "Moderate" moderate)
56
+ (const :tag "Normal" normal)
57
+ (const :tag "Low" low)
58
+ (const :tag "Trivial" trivial)))
59
+
60
+ (defcustom enotify-spectator-alert-use-separate-log-buffers nil
61
+ "whether enotify-spectator should use different alert log
62
+ buffers for each project."
63
+ :group 'enotify-spectator
64
+ :type 'boolean)
65
+
66
+
67
+ (defcustom enotify-spectator-change-face-timeout nil
68
+ "amount of seconds after which the notification face should be changed."
69
+ :group 'enotify-spectator
70
+ :type '(choice (const nil) integer))
71
+
72
+ (defcustom enotify-spectator-timeout-face :standard
73
+ "face to apply to the notification text on timeout"
74
+ :group 'enotify-spectator
75
+ :type '(choice (const :tag "Standard enotify face" :standard )
76
+ (const :tag "Standard enotify success face" :success)
77
+ (const :tag "Standard enotify warning face" :warning)
78
+ (const :tag "Standard enotify failure face" :failure)
79
+ face))
80
+
81
+ (defcustom enotify-rspec-handler 'enotify-rspec-handler
82
+ "Message handler for enotify spectator-emacs notifications.
83
+ This function should take 2 arguments, (id data), where id is the
84
+ enotify slot id, and data contains the rspec output.
85
+ The default handler just writes the results in a buffer in org-mode.")
86
+
87
+ (defvar enotify-rspec-result-message-handler 'enotify-rspec-result-message-handler
88
+ "Don't touch me - used by spectator-emacs.")
89
+
90
+ (defvar enotify-rspec-mouse-1-handler 'enotify-rspec-mouse-1-handler
91
+ "Mouse-1 handler function. It takes an event parameter. See enotify README for details.")
92
+
93
+ (defcustom spectator-get-project-root-dir-function 'rinari-root
94
+ "Function used to get ruby project root."
95
+ :group 'enotify-spectator)
96
+
97
+ (defcustom spectator-test-server-cmd "spork"
98
+ "Test server command - change this to bundle exec spork if you are using bundle.
99
+ Change to nil if you don't want to use any test server."
100
+ :group 'enotify-spectator)
101
+
102
+ (defcustom spectator-watchr-cmd "spectator-emacs"
103
+ "Command to run watchr - change this to bundle exec watchr if you are using bundle."
104
+ :group 'enotify-spectator)
105
+
106
+
107
+
108
+ ;;;; Alert.el stuff
109
+
110
+ (when (featurep 'alert)
111
+ (defun enotify-spectator-alert-id (info)
112
+ (car (plist-get info :data)))
113
+ (defun enotify-spectator-alert-face (info)
114
+ (enotify-face (cdr (plist-get info :data))))
115
+
116
+ (defun enotify-spectator-chomp (str)
117
+ "Chomp leading and tailing whitespace from STR."
118
+ (while (string-match "\\`\n+\\|^\\s-+\\|\\s-+$\\|\n+\\'"
119
+ str)
120
+ (setq str (replace-match "" t t str)))
121
+ str)
122
+
123
+ (defun* enotify-spectator-colorized-summary (info &optional (with-timestamp t))
124
+ (let* ((s+t (plist-get info :message))
125
+ (summary (if with-timestamp s+t (car (last (split-string s+t ":"))))))
126
+ (enotify-spectator-chomp
127
+ (propertize summary 'face (enotify-spectator-alert-face info)))))
128
+
129
+ (defun enotify-spectator-alert-log (info)
130
+ (let ((bname (format "*Alerts - Spectator-emacs [%s]*" (enotify-spectator-alert-id info))))
131
+ (with-current-buffer
132
+ (get-buffer-create bname)
133
+ (goto-char (point-max))
134
+ (insert (format-time-string "%H:%M %p - ")
135
+ (enotify-spectator-colorized-summary info nil)
136
+ ?\n))))
137
+
138
+ (defun alert-spectator-notify (info)
139
+ "alert.el notifier function for enotify-spectator."
140
+ (when enotify-spectator-alert-use-separate-log-buffers
141
+ (enotify-spectator-alert-log info))
142
+ (message "%s: %s"
143
+ (alert-colorize-message (format "Enotify - spectator-emacs [%s]:"
144
+ (enotify-spectator-alert-id info))
145
+ (plist-get info :severity))
146
+ (enotify-spectator-colorized-summary info)))
147
+
148
+ ;;; enotify-spectator alert style
149
+ (alert-define-style 'enotify-spectator
150
+ :title "Display message in minibuffer for enotify-spectator alerts"
151
+ :notifier #'alert-spectator-notify
152
+ :remover #'alert-message-remove)
153
+
154
+ (defun enotify-spectator-summary (id)
155
+ "Extract summary from enotify notifiations sent by spectator-emacs."
156
+ (let* ((notification (enotify-mode-line-notification id))
157
+ (help-text (plist-get notification :help))
158
+ (face (enotify-face (plist-get notification :face)))
159
+ (summary-text (nth 1 (split-string help-text "\n"))))
160
+ summary-text))
161
+
162
+
163
+ (defun enotify-spectator-face (id)
164
+ "Extracts the face used for the enotify notification sent by spectator-emacs"
165
+ (enotify-face (plist-get (enotify-mode-line-notification id) :face)))
166
+
167
+ ;;; Use enotify-spectator style for all the alerts whose category is enotify-spectator
168
+ (alert-add-rule :predicate (lambda (info)
169
+ (eq (plist-get info :category)
170
+ 'enotify-spectator))
171
+ :style 'enotify-spectator))
172
+
173
+
174
+ ;;;; Enotify stuff
175
+
176
+ (defun enotify-rspec-result-buffer-name (id)
177
+ (format "*RSpec Results: %s*" id))
178
+
179
+ (defun enotify-rspec-handler (id data)
180
+ (let ((buf (get-buffer-create (enotify-rspec-result-buffer-name id))))
181
+ (save-current-buffer
182
+ (set-buffer buf)
183
+ (erase-buffer)
184
+ (insert data)
185
+ (flet ((message (&rest args) (apply 'format args)))
186
+ (org-mode)))))
187
+
188
+ (defun enotify-rspec-result-message-handler (id data)
189
+ (when enotify-spectator-change-face-timeout
190
+ (run-with-timer enotify-spectator-change-face-timeout nil
191
+ 'enotify-change-notification-face
192
+ id enotify-spectator-timeout-face))
193
+ (when (and enotify-spectator-use-alert (featurep 'alert))
194
+ (let ((alert-log-messages (if enotify-spectator-alert-use-separate-log-buffers
195
+ nil
196
+ alert-log-messages)))
197
+ (alert (enotify-spectator-summary id)
198
+ :title id
199
+ :data (cons id (enotify-spectator-face id))
200
+ :category 'enotify-spectator
201
+ :severity enotify-spectator-alert-severity)))
202
+ (funcall enotify-rspec-handler id data))
203
+
204
+ (defun enotify-rspec-mouse-1-handler (event)
205
+ (interactive "e")
206
+ (switch-to-buffer-other-window
207
+ (enotify-rspec-result-buffer-name
208
+ (enotify-event->slot-id event))))
209
+
210
+
211
+ ;;;; Rinari / spectator-emacs stuff
212
+ (defvar spectator-script " # -*-ruby-*-
213
+ require 'rspec-rails-watchr-emacs'
214
+ @specs_watchr ||= Rspec::Rails::Watchr.new(self,
215
+ ## uncomment the line below if you are using RspecOrgFormatter
216
+ # :error_count_line => -6,
217
+ ## uncomment to customize the notification messages that appear on the notification area
218
+ # :notification_message => {:failure => 'F', :success => 'S', :pending => 'P'},
219
+ ## uncomment to customize the message faces (underscores are changed to dashes)
220
+ # :notification_face => {
221
+ # :failure => :my_failure_face, #will be `my-failure-face' on emacs
222
+ # :success => :my_success_face,
223
+ # :pending => :my_pending_face},
224
+ ## uncomment for custom matcher!
225
+ # :custom_matcher => lambda { |path, specs| puts 'Please fill me!' }
226
+ ## uncomment for custom summary extraction
227
+ # :custom_extract_summary_proc => lambda { |results| puts 'Please Fill me!' }
228
+ ## uncomment for custom enotify slot id (defaults to the base directory name of
229
+ ## your application rendered in CamelCase
230
+ # :slot_id => 'My slot id'
231
+ )
232
+ ")
233
+
234
+
235
+ (defun spectator-generate-script ()
236
+ "Creates a spectator-emacs script in the project root directory"
237
+ (let ((dir (funcall spectator-get-project-root-dir-function)))
238
+ (when dir
239
+ (with-temp-file (concat dir "/.spectator")
240
+ (insert spectator-script)))))
241
+
242
+ (defun spectator-script ()
243
+ (interactive)
244
+ (find-file (concat (funcall spectator-get-project-root-dir-function) "/.spectator")))
245
+
246
+ (defun spectator-run-in-shell (cmd &optional dir bufname)
247
+ (let* ((default-directory (or dir default-directory))
248
+ (shproc (shell bufname)))
249
+ (comint-send-string shproc (concat cmd "\n"))))
250
+
251
+ (defun spectator-app-name ()
252
+ (let ((root-dir (funcall spectator-get-project-root-dir-function)))
253
+ (when root-dir
254
+ (apply 'concat
255
+ (mapcar 'capitalize
256
+ (split-string (file-name-nondirectory
257
+ (directory-file-name
258
+ root-dir))
259
+ "[^a-zA-Z0-9]"))))))
260
+
261
+ (defun spectator ()
262
+ (interactive)
263
+ (let ((project-root (funcall spectator-get-project-root-dir-function))
264
+ (app-name (spectator-app-name)))
265
+ (spectator-run-in-shell spectator-test-server-cmd
266
+ project-root
267
+ (concat "*Spork - " app-name "*"))
268
+ (spectator-run-in-shell (concat spectator-watchr-cmd " .spectator")
269
+ project-root
270
+ (concat "*Spectator - " app-name "*"))))
271
+
272
+ ;;; Some utilities
273
+
274
+ (defun spectator-find-spectator-1 (pattern)
275
+ (let ((bnames (mapcar 'buffer-name (buffer-list)))
276
+ (app-name (spectator-app-name)))
277
+ (when app-name
278
+ (find-if (lambda (el) (string-match (format "%s.*%s" pattern app-name) el))
279
+ bnames))))
280
+ (defun spectator-maybe-switch-to-buffer (buf &optional msg)
281
+ (if buf
282
+ (switch-to-buffer buf)
283
+ (message "Could not open buffer. %s" (or msg "Did you run spectator? Try M-x spectator RET."))))
284
+
285
+ (defun spectator-find-spectator ()
286
+ (interactive)
287
+ (spectator-maybe-switch-to-buffer (spectator-find-spectator-1 "*Spectator")))
288
+
289
+ (defun spectator-find-spectator-results ()
290
+ (interactive)
291
+ (spectator-maybe-switch-to-buffer (spectator-find-spectator-1 "*RSpec Results")
292
+ "Either spectator is not running or no tests have been executed yet."))
293
+
294
+ (defun spectator-find-spectator-spork ()
295
+ (interactive)
296
+ (spectator-maybe-switch-to-buffer (spectator-find-spectator-1 "*Spork")))
297
+
298
+ (provide 'enotify-spectator)
299
+
300
+ ;;; enotify-spectator.el ends here
@@ -1,6 +1,6 @@
1
1
  module Spectator
2
2
  module Emacs
3
3
  # spectator-emacs version
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
6
6
  end
@@ -3,6 +3,12 @@ require 'spectator'
3
3
  require 'socket'
4
4
  require 'open4'
5
5
 
6
+ class NilClass
7
+ def to_lisp
8
+ 'nil'
9
+ end
10
+ end
11
+
6
12
  class Object
7
13
  # Returns a string representing the object as a lisp sexp.
8
14
  def to_lisp
@@ -294,7 +300,7 @@ module Spectator
294
300
 
295
301
  # Registers the slot named `@enotify_slot_id` with Enotify.
296
302
  def enotify_register
297
- enotify_send :register => @enotify_slot_id, :handler_fn => :enotify_rspec_result_message_handler
303
+ enotify_send :register => @enotify_slot_id, :handler_fn => "tdd"
298
304
  end
299
305
 
300
306
  # Sends a notification to the enotify host with the RSpec results.
@@ -312,9 +318,9 @@ module Spectator
312
318
  :text => @notification_messages[status],
313
319
  :face => @notification_face[status],
314
320
  :help => format_tooltip(stats),
315
- :mouse_1 => :enotify_rspec_mouse_1_handler
321
+ :mouse_1 => "tdd"
316
322
  },
317
- :data => stdout
323
+ :data => { :mode => @report_buffer_mode, :report_text => stdout }
318
324
  }
319
325
 
320
326
  enotify_send message
@@ -394,6 +400,12 @@ module Spectator
394
400
  # the faces to apply to the notification *icon* in the Emacs modeline.
395
401
  # Values must be {Symbol}s, like for example `:font_lock_constant_face`
396
402
  # in order to use Emacs' `font-lock-warning-face`.
403
+ # ##### :report_buffer_mode ({String})
404
+ # The major mode to use for the report buffer on emacs.
405
+ # It must be specified in the same way as an emacs magic comment, i.e.
406
+ # without the trailing "-mode".
407
+ # For example, if you are using RspecOrgFormatter, and you want to use
408
+ # org-mode to display the report, specify `"org"`.
397
409
  # Defaults to
398
410
  #
399
411
  # ```
@@ -428,6 +440,7 @@ module Spectator
428
440
  puts "======= OPTIONS ======="
429
441
  options.each {|k, v| puts "#{k} => #{v}"}
430
442
  @enotify_host = options[:enotify_host]
443
+ @report_buffer_mode = options[:report_buffer_mode]
431
444
  @enotify_port = options[:enotify_port]
432
445
  @notification_messages = options[:notification_messages]
433
446
  @notification_face = options[:notification_face]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spectator-emacs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-03 00:00:00.000000000 Z
12
+ date: 2013-02-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rdoc
@@ -195,6 +195,7 @@ files:
195
195
  - README.md
196
196
  - Rakefile
197
197
  - bin/spectator-emacs
198
+ - emacs/enotify-spectator.el
198
199
  - lib/spectator/emacs.rb
199
200
  - lib/spectator/emacs/version.rb
200
201
  - spec/emacs_spec.rb
@@ -216,7 +217,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
216
217
  version: '0'
217
218
  segments:
218
219
  - 0
219
- hash: -2575753694497142155
220
+ hash: -703244129636977448
220
221
  required_rubygems_version: !ruby/object:Gem::Requirement
221
222
  none: false
222
223
  requirements:
@@ -225,7 +226,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
225
226
  version: '0'
226
227
  segments:
227
228
  - 0
228
- hash: -2575753694497142155
229
+ hash: -703244129636977448
229
230
  requirements: []
230
231
  rubyforge_project:
231
232
  rubygems_version: 1.8.24