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 +1 -1
- data/README.md +5 -3
- data/Rakefile +1 -1
- data/emacs/enotify-spectator.el +300 -0
- data/lib/spectator/emacs/version.rb +1 -1
- data/lib/spectator/emacs.rb +16 -3
- metadata +5 -4
data/Gemfile.lock
CHANGED
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
|
-
|
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
@@ -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
|
data/lib/spectator/emacs.rb
CHANGED
@@ -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 =>
|
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 =>
|
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.
|
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-
|
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: -
|
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: -
|
229
|
+
hash: -703244129636977448
|
229
230
|
requirements: []
|
230
231
|
rubyforge_project:
|
231
232
|
rubygems_version: 1.8.24
|