guard-sclang 0.1.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CONTRIBUTING.md +4 -0
- data/README.md +57 -12
- data/lib/guard/sclang.rb +67 -15
- data/lib/guard/sclang/version.rb +1 -1
- data/unit-test-cli.scd +3 -1
- metadata +17 -4
- data/lib/guard/sclang.rb.orig +0 -166
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ea35a0bfba850d4f17a1f3cf76f1df062053c28630e5eb17f7ccafa8f221de99
|
4
|
+
data.tar.gz: 30aa8b33db6642b9490f3ac451943acabfb6fe63e0a50bac88d240982560de62
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6191fde9ce607a751469a55c78250c7ba77106c7beb02e9cc43039d1d87db39d0d709806664539ba056373c49807d5153d59991e2cffd20e0b9c4dbd68fbbb9c
|
7
|
+
data.tar.gz: c7d8a6ec4df2c08a2391ddf2ffb589f8d04b55c0ba979ce1346c743c62799cfeb6199d55823f7ff6e9ddd4dfc59c8ccbc6054145b71e95840af1eabe1b46c3d4
|
data/CONTRIBUTING.md
CHANGED
@@ -19,3 +19,7 @@ please follow these
|
|
19
19
|
[guidelines on contributing](http://blog.adamspiers.org/2012/11/10/7-principles-for-contributing-patches-to-software-projects/) so that you can help me to help you ;-)
|
20
20
|
|
21
21
|
Thanks in advance!
|
22
|
+
|
23
|
+
## Guide for maintainers
|
24
|
+
|
25
|
+
See [`MAINTAINERS.md`](MAINTAINERS.md).
|
data/README.md
CHANGED
@@ -1,13 +1,17 @@
|
|
1
|
+
[![Build Status](https://travis-ci.org/aspiers/guard-sclang.svg?branch=master)](https://travis-ci.org/aspiers/guard-sclang)
|
2
|
+
|
1
3
|
Guard::Sclang
|
2
4
|
=============
|
3
5
|
|
4
|
-
This [Guard](http://guardgem.org/) plugin allows you to run
|
5
|
-
|
6
|
-
|
6
|
+
This [Guard](http://guardgem.org/) plugin allows you to run
|
7
|
+
SuperCollider [`UnitTest` test
|
8
|
+
suites](http://doc.sccode.org/Classes/UnitTest.html) automatically
|
9
|
+
when files are added or altered, so that you can immediately see the
|
10
|
+
impact of code changes on your tests.
|
7
11
|
|
8
12
|
|
9
|
-
|
10
|
-
|
13
|
+
Installation
|
14
|
+
------------
|
11
15
|
|
12
16
|
Make sure you have [Guard](http://guardgem.org/) installed.
|
13
17
|
|
@@ -15,17 +19,25 @@ Install the gem with:
|
|
15
19
|
|
16
20
|
gem install guard-sclang
|
17
21
|
|
18
|
-
Or add it to your `Gemfile
|
22
|
+
Or, better, add it to your `Gemfile`, and then use
|
23
|
+
[Bundler](http://bundler.io/) to install it:
|
19
24
|
|
20
|
-
gem 'guard-sclang'
|
25
|
+
echo "gem 'guard-sclang'" >> Gemfile
|
26
|
+
bundle install
|
21
27
|
|
22
|
-
And then add a basic setup to your `Guardfile`:
|
23
28
|
|
24
|
-
|
29
|
+
Configuring a `Guardfile`
|
30
|
+
---------------------------
|
25
31
|
|
32
|
+
Before you can launch Guard, you need to configure a `Guardfile` which
|
33
|
+
tells Guard which of your SuperCollider tests to run via the
|
34
|
+
`guard-sclang` plugin.
|
26
35
|
|
27
|
-
|
28
|
-
|
36
|
+
You can create a stub `Guardfile` from a built-in template via:
|
37
|
+
|
38
|
+
bundle exec guard init sclang
|
39
|
+
|
40
|
+
The rest of this section explains how to configure the `Guardfile`.
|
29
41
|
|
30
42
|
When one or more files matching a `watch` block's regular expression
|
31
43
|
changes, guard-sclang simply runs the UnitTest subclass returned by
|
@@ -76,7 +88,7 @@ end
|
|
76
88
|
|
77
89
|
### Other options
|
78
90
|
|
79
|
-
To run everything on start pass `:all_on_start` to `#guard`:
|
91
|
+
To run everything on start, pass `:all_on_start` to `#guard`:
|
80
92
|
|
81
93
|
``` ruby
|
82
94
|
guard :sclang, all_on_start: true do
|
@@ -84,6 +96,39 @@ guard :sclang, all_on_start: true do
|
|
84
96
|
end
|
85
97
|
```
|
86
98
|
|
99
|
+
To run everything after previously failing tests succeeded, pass
|
100
|
+
`:all_after_pass` to `#guard`:
|
101
|
+
|
102
|
+
``` ruby
|
103
|
+
guard :sclang, all_after_pass: true do
|
104
|
+
...
|
105
|
+
end
|
106
|
+
```
|
107
|
+
|
108
|
+
|
109
|
+
Usage
|
110
|
+
-----
|
111
|
+
|
112
|
+
Once you have set up your `Guardfile` with the `guard-sclang` plugin
|
113
|
+
enabled, you are ready to launch Guard.
|
114
|
+
|
115
|
+
`guard-sclang` assumes that the `sclang` interpreter is to be found
|
116
|
+
somewhere on your `$PATH`. If you installed SuperCollider on Linux
|
117
|
+
via a distribution package, this should happen automatically, in which
|
118
|
+
case you can simply launch Guard by typing this into your shell:
|
119
|
+
|
120
|
+
bundle exec guard
|
121
|
+
|
122
|
+
However if you installed from source, or you are using MacOS, maybe
|
123
|
+
`sclang` won't be on the `$PATH`, in which case you will need to set
|
124
|
+
it. This can either be done temporarily for each invocation of Guard,
|
125
|
+
e.g.
|
126
|
+
|
127
|
+
PATH=/path/to/dir/containing/sclang:$PATH bundle exec guard
|
128
|
+
|
129
|
+
or by configuring your interactive shell setup (e.g. `~/.bashrc`) to
|
130
|
+
set `$PATH` on startup.
|
131
|
+
|
87
132
|
|
88
133
|
Development / support / feedback
|
89
134
|
--------------------------------
|
data/lib/guard/sclang.rb
CHANGED
@@ -6,10 +6,13 @@ require 'guard/sclang/version'
|
|
6
6
|
|
7
7
|
module Guard
|
8
8
|
class Sclang < Plugin
|
9
|
+
attr_accessor :last_failed
|
10
|
+
|
9
11
|
def initialize(options={})
|
10
12
|
super
|
11
13
|
options[:args] ||= []
|
12
14
|
options[:timeout] ||= 3
|
15
|
+
@last_failed = false
|
13
16
|
end
|
14
17
|
|
15
18
|
# Calls #run_all if the :all_on_start option is present.
|
@@ -21,10 +24,13 @@ module Guard
|
|
21
24
|
def stop
|
22
25
|
end
|
23
26
|
|
24
|
-
#
|
27
|
+
# Test for all files which match this guard.
|
25
28
|
def run_all
|
26
|
-
|
27
|
-
|
29
|
+
run_sclang
|
30
|
+
end
|
31
|
+
|
32
|
+
def all_paths
|
33
|
+
Compat.matching_files(self, Dir.glob('{,**/}*.sc{,d}'))
|
28
34
|
end
|
29
35
|
|
30
36
|
def run_on_additions(paths)
|
@@ -53,10 +59,19 @@ module Guard
|
|
53
59
|
else
|
54
60
|
title = tester.join " "
|
55
61
|
end
|
56
|
-
[cmd, title]
|
62
|
+
return [cmd, title]
|
63
|
+
end
|
64
|
+
|
65
|
+
def run_sclang(paths=nil)
|
66
|
+
success = run_sclang_once(paths || all_paths)
|
67
|
+
if paths && options[:all_after_pass] && success && last_failed
|
68
|
+
success = run_all
|
69
|
+
end
|
70
|
+
@last_failed = !success
|
71
|
+
return success
|
57
72
|
end
|
58
73
|
|
59
|
-
def
|
74
|
+
def run_sclang_once(paths)
|
60
75
|
paths = paths.uniq
|
61
76
|
cmd, title = _get_cmd_and_title(paths)
|
62
77
|
|
@@ -64,17 +79,40 @@ module Guard
|
|
64
79
|
print Compat::UI.color("=" * (ENV["COLUMNS"] || "72").to_i, :blue)
|
65
80
|
print Compat::UI.color("Running: " + cmd.join(" ") + "\n", :blue)
|
66
81
|
|
67
|
-
|
82
|
+
run_status, exit_status = _run_cmd(cmd, title)
|
68
83
|
|
69
|
-
|
84
|
+
if run_status
|
85
|
+
return run_status == :success
|
86
|
+
else
|
87
|
+
# Couldn't figure out the result from the output. Even if
|
88
|
+
# the exit code is 0, this could simply mean something went
|
89
|
+
# wrong in unit-test-cli.scd's handling of an error, so we
|
90
|
+
# assume the worst.
|
70
91
|
_handle_missing_status(exit_status, title)
|
92
|
+
return :failed
|
71
93
|
end
|
72
94
|
end
|
73
95
|
|
96
|
+
# Returns [run_status, exit_status] pair.
|
97
|
+
#
|
98
|
+
# Run the test runner, add colour for PASS/FAIL/ERROR/WARNING, and
|
99
|
+
# try to extract the final test result (100% pass / some failures
|
100
|
+
# / compilation error) from the runner output. If the test result
|
101
|
+
# is successfully extracted from the output, the appropriate
|
102
|
+
# notification will be sent, and the run_status value returned
|
103
|
+
# will be :success or :failed. However if something goes wrong
|
104
|
+
# then we won't be able to determine the result from the output,
|
105
|
+
# in which case at least we capture the exit status of the runner
|
106
|
+
# process, and success is determined based on this exit status.
|
107
|
+
#
|
108
|
+
# Note that due to quirks in SuperCollider which are not yet
|
109
|
+
# understood, it is possible for the exit code to be non-zero even
|
110
|
+
# when the test suite passes 100% and the test runner is
|
111
|
+
# apparently working as designed.
|
74
112
|
def _run_cmd(cmd, title)
|
75
113
|
command, *args = *cmd
|
76
114
|
|
77
|
-
|
115
|
+
run_status = nil
|
78
116
|
exit_status = nil
|
79
117
|
|
80
118
|
# Using PTY instead of Open3.popen2e should work around
|
@@ -87,7 +125,7 @@ module Guard
|
|
87
125
|
colors =
|
88
126
|
if line =~ /^PASS:/
|
89
127
|
[:green]
|
90
|
-
elsif line =~ /^FAIL
|
128
|
+
elsif line =~ /^FAIL:|^There were failures/
|
91
129
|
[:red]
|
92
130
|
elsif line =~ /^ERROR:/
|
93
131
|
[:bright, :red]
|
@@ -97,10 +135,18 @@ module Guard
|
|
97
135
|
[]
|
98
136
|
end
|
99
137
|
|
100
|
-
|
101
|
-
if
|
102
|
-
|
103
|
-
|
138
|
+
line_status, msg, line = _check_line_for_status(line)
|
139
|
+
if line_status
|
140
|
+
# Allow for multiple summary lines just in case, e.g.
|
141
|
+
# some with no failures and others with failures.
|
142
|
+
# Hopefully this won't happen though.
|
143
|
+
if line_status == :success
|
144
|
+
run_status ||= line_status
|
145
|
+
else
|
146
|
+
run_status = line_status
|
147
|
+
end
|
148
|
+
|
149
|
+
Compat::UI.notify(msg, title: title, image: line_status)
|
104
150
|
end
|
105
151
|
|
106
152
|
print Compat::UI.color(line, *colors)
|
@@ -112,6 +158,9 @@ module Guard
|
|
112
158
|
rescue Errno::EIO => e
|
113
159
|
# Ran out of output to read
|
114
160
|
exit_status = $?
|
161
|
+
unless exit_status
|
162
|
+
Compat::UI.error("$? returned #{exit_status}")
|
163
|
+
end
|
115
164
|
end
|
116
165
|
end
|
117
166
|
rescue PTY::ChildExited => e
|
@@ -119,7 +168,7 @@ module Guard
|
|
119
168
|
exit_status = e.status.exitstatus
|
120
169
|
end
|
121
170
|
|
122
|
-
[
|
171
|
+
[run_status, exit_status]
|
123
172
|
end
|
124
173
|
|
125
174
|
def _check_line_for_status(line)
|
@@ -140,13 +189,16 @@ module Guard
|
|
140
189
|
[status, msg, line]
|
141
190
|
end
|
142
191
|
|
192
|
+
# Couldn't figure out the result from the output, so rely on
|
193
|
+
# the exit code instead.
|
143
194
|
def _handle_missing_status(exit_status, title)
|
144
195
|
msg = "Pid %d exited with status %d" % [exit_status.pid, exit_status.exitstatus]
|
145
|
-
status = exit_status
|
196
|
+
status = exit_status.success? ? :success : :failed
|
146
197
|
Compat::UI.notify(msg, title: title, image: status)
|
147
198
|
level = status == :success ? :warning : :error
|
148
199
|
Compat::UI.send(level, msg)
|
149
200
|
Compat::UI.warning("Didn't find test results in output")
|
201
|
+
exit_status.success?
|
150
202
|
end
|
151
203
|
end
|
152
204
|
end
|
data/lib/guard/sclang/version.rb
CHANGED
data/unit-test-cli.scd
CHANGED
@@ -31,6 +31,8 @@ var excludes = [
|
|
31
31
|
// Have to wrap this in a Task so that we can wait.
|
32
32
|
t = Task.new {
|
33
33
|
UnitTest.reset;
|
34
|
+
//UnitTest.reportPasses = false;
|
35
|
+
UnitTest.passVerbosity = UnitTest.brief;
|
34
36
|
if (thisProcess.argv.isEmpty) {
|
35
37
|
UnitTest.allSubclasses.do { |testClass|
|
36
38
|
if (excludes.includes(testClass.asString).not) {
|
@@ -44,7 +46,7 @@ t = Task.new {
|
|
44
46
|
} {
|
45
47
|
thisProcess.argv.do { |name|
|
46
48
|
if (name.contains("/")) {
|
47
|
-
name = name.basename.
|
49
|
+
name = PathName(name.basename).fileNameWithoutExtension;
|
48
50
|
};
|
49
51
|
if (name.contains(":")) {
|
50
52
|
UnitTest.runTest(name);
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: guard-sclang
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Spiers
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-04-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: guard
|
@@ -44,6 +44,20 @@ dependencies:
|
|
44
44
|
- - "~>"
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '1.0'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: bundler
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.13.0
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 1.13.0
|
47
61
|
- !ruby/object:Gem::Dependency
|
48
62
|
name: rake
|
49
63
|
requirement: !ruby/object:Gem::Requirement
|
@@ -98,7 +112,6 @@ files:
|
|
98
112
|
- LICENSE
|
99
113
|
- README.md
|
100
114
|
- lib/guard/sclang.rb
|
101
|
-
- lib/guard/sclang.rb.orig
|
102
115
|
- lib/guard/sclang/templates/Guardfile
|
103
116
|
- lib/guard/sclang/version.rb
|
104
117
|
- unit-test-cli.scd
|
@@ -122,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
135
|
version: '0'
|
123
136
|
requirements: []
|
124
137
|
rubyforge_project:
|
125
|
-
rubygems_version: 2.6
|
138
|
+
rubygems_version: 2.7.6
|
126
139
|
signing_key:
|
127
140
|
specification_version: 4
|
128
141
|
summary: Guard gem for running sclang commands
|
data/lib/guard/sclang.rb.orig
DELETED
@@ -1,166 +0,0 @@
|
|
1
|
-
require 'open3'
|
2
|
-
require 'pathname'
|
3
|
-
|
4
|
-
require 'guard/compat/plugin'
|
5
|
-
require 'guard/sclang/version'
|
6
|
-
|
7
|
-
module Guard
|
8
|
-
class Sclang < Plugin
|
9
|
-
<<<<<<< HEAD
|
10
|
-
def initialize
|
11
|
-
=======
|
12
|
-
def initialize(options)
|
13
|
-
>>>>>>> c984ace... fix tests
|
14
|
-
super
|
15
|
-
options[:args] ||= []
|
16
|
-
options[:timeout] ||= 3
|
17
|
-
end
|
18
|
-
|
19
|
-
# Calls #run_all if the :all_on_start option is present.
|
20
|
-
def start
|
21
|
-
run_all if options[:all_on_start]
|
22
|
-
end
|
23
|
-
|
24
|
-
# Defined only to make callback(:stop_begin) and callback(:stop_end) working
|
25
|
-
def stop
|
26
|
-
end
|
27
|
-
|
28
|
-
# Call #run_on_change for all files which match this guard.
|
29
|
-
def run_all
|
30
|
-
all = Compat.matching_files(self, Dir.glob('{,**/}*.sc{,d}'))
|
31
|
-
run_on_modifications(all)
|
32
|
-
end
|
33
|
-
|
34
|
-
def run_on_additions(paths)
|
35
|
-
run_sclang(paths)
|
36
|
-
end
|
37
|
-
|
38
|
-
def run_on_modifications(paths)
|
39
|
-
run_sclang(paths)
|
40
|
-
end
|
41
|
-
|
42
|
-
def run_on_removals(paths)
|
43
|
-
run_sclang(paths)
|
44
|
-
end
|
45
|
-
|
46
|
-
def _get_cmd_and_title(paths)
|
47
|
-
# -i scqt is required to compile IDE libraries, otherwise we get
|
48
|
-
# compile warnings on Quarks which extend classes provided by those
|
49
|
-
# IDE libraries.
|
50
|
-
here = Pathname.new(__FILE__).dirname
|
51
|
-
runner = here.parent.parent + "unit-test-cli.scd"
|
52
|
-
tester = ["sclang"] + options[:args] + [runner.to_s]
|
53
|
-
cmd = ["timeout", options[:timeout].to_s] + tester
|
54
|
-
if paths
|
55
|
-
cmd += paths
|
56
|
-
title = paths.join " "
|
57
|
-
else
|
58
|
-
title = tester.join " "
|
59
|
-
end
|
60
|
-
[cmd, title]
|
61
|
-
end
|
62
|
-
|
63
|
-
def run_sclang(paths)
|
64
|
-
cmd, title = _get_cmd_and_title(paths)
|
65
|
-
|
66
|
-
outerr = ''
|
67
|
-
print Compat::UI.color("=" * (ENV["COLUMNS"] || "72").to_i, :blue)
|
68
|
-
print Compat::UI.color("Running: " + cmd.join(" ") + "\n", :blue)
|
69
|
-
|
70
|
-
got_status, exit_status = _run_cmd(cmd, title)
|
71
|
-
|
72
|
-
unless got_status
|
73
|
-
_handle_missing_status(exit_status)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def _run_cmd(cmd, title)
|
78
|
-
got_status = false
|
79
|
-
exit_status = nil
|
80
|
-
|
81
|
-
Open3.popen2e(*cmd) do |stdin, stdouterr, wait_thr|
|
82
|
-
stdouterr.each do |line|
|
83
|
-
#Compat::UI.info(line)
|
84
|
-
colors =
|
85
|
-
if line =~ /^PASS:/
|
86
|
-
[:green]
|
87
|
-
elsif line =~ /^FAIL:/
|
88
|
-
[:red]
|
89
|
-
elsif line =~ /^ERROR:/
|
90
|
-
[:bright, :red]
|
91
|
-
elsif line =~ /^WARNING:/
|
92
|
-
[:yellow]
|
93
|
-
else
|
94
|
-
[]
|
95
|
-
end
|
96
|
-
|
97
|
-
status, msg, line = _check_line_for_status(line)
|
98
|
-
if status
|
99
|
-
got_status = true
|
100
|
-
Compat::UI.notify(msg, title: title, image: status)
|
101
|
-
end
|
102
|
-
|
103
|
-
print Compat::UI.color(line, *colors)
|
104
|
-
end
|
105
|
-
|
106
|
-
exit_status = wait_thr.value
|
107
|
-
end
|
108
|
-
|
109
|
-
[got_status, exit_status]
|
110
|
-
end
|
111
|
-
|
112
|
-
def _check_line_for_status(line)
|
113
|
-
status, msg = nil
|
114
|
-
|
115
|
-
if line =~ /Finished running test\(s\): (\d+ pass(?:es), (\d+) failures?)/
|
116
|
-
msg, failures = $1, $2
|
117
|
-
status = failures == "0" ? :success : :failed # :pending also supported
|
118
|
-
elsif line =~ /(Library has not been compiled successfully)\./
|
119
|
-
msg = $1
|
120
|
-
status = :failed
|
121
|
-
end
|
122
|
-
|
123
|
-
if status
|
124
|
-
line = Compat::UI.color(line, status == :success ? :green : :red)
|
125
|
-
end
|
126
|
-
|
127
|
-
[status, msg, line]
|
128
|
-
end
|
129
|
-
|
130
|
-
def _handle_missing_status(exit_status)
|
131
|
-
msg = "Pid %d exited with status %d" % [exit_status.pid, exit_status]
|
132
|
-
status = exit_status == 0 ? :success : :failed
|
133
|
-
Compat::UI.notify(msg, title: title, image: status)
|
134
|
-
level = status == :success ? :warning : :error
|
135
|
-
Compat::UI.send(level, msg)
|
136
|
-
Compat::UI.warning("Didn't find test results in output")
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
class Dsl
|
141
|
-
# Easy method to display a notification
|
142
|
-
def n(msg, title='', image=nil)
|
143
|
-
Compat::UI.notify(msg, :title => title, :image => image)
|
144
|
-
end
|
145
|
-
|
146
|
-
# Eager prints the result for stdout and stderr as it would be written when
|
147
|
-
# running the command from the terminal. This is useful for long running
|
148
|
-
# tasks.
|
149
|
-
def eager(command)
|
150
|
-
require 'pty'
|
151
|
-
|
152
|
-
begin
|
153
|
-
PTY.spawn command do |r, w, pid|
|
154
|
-
begin
|
155
|
-
$stdout.puts
|
156
|
-
r.each {|line| print line }
|
157
|
-
rescue Errno::EIO
|
158
|
-
# the process has finished
|
159
|
-
end
|
160
|
-
end
|
161
|
-
rescue PTY::ChildExited
|
162
|
-
$stdout.puts "The child process exited!"
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|