guard-sclang 0.1.0 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ec4f743fda4d9f4624f0ac998c2c56116f41f7d7
4
- data.tar.gz: 73d9b97ca0bd8e8693bc2e0f0e22756f7e08537d
2
+ SHA256:
3
+ metadata.gz: ea35a0bfba850d4f17a1f3cf76f1df062053c28630e5eb17f7ccafa8f221de99
4
+ data.tar.gz: 30aa8b33db6642b9490f3ac451943acabfb6fe63e0a50bac88d240982560de62
5
5
  SHA512:
6
- metadata.gz: ccb809137015499345dd6aa8166de1934d79105110fcecc943f4d4b5e044b125ac5317b3812c64aaf9681f70b26e914abc63b898a33bbfa508ffa657af5a3c13
7
- data.tar.gz: d32873acf76ad416693b03cbcd1d97a1eabccd394158143905a474b978ffb10f578394cb28a5be313860ac2a22000e43b1ecfdf64561c0130cb56e95ea3fe488
6
+ metadata.gz: 6191fde9ce607a751469a55c78250c7ba77106c7beb02e9cc43039d1d87db39d0d709806664539ba056373c49807d5153d59991e2cffd20e0b9c4dbd68fbbb9c
7
+ data.tar.gz: c7d8a6ec4df2c08a2391ddf2ffb589f8d04b55c0ba979ce1346c743c62799cfeb6199d55823f7ff6e9ddd4dfc59c8ccbc6054145b71e95840af1eabe1b46c3d4
@@ -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 SuperCollider [`UnitTest` test
5
- suites](http://doc.sccode.org/Classes/UnitTest.html) commands when
6
- files are added or altered.
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
- Install
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
- guard init sclang
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
- Usage
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
  --------------------------------
@@ -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
- # Call #run_on_change for all files which match this guard.
27
+ # Test for all files which match this guard.
25
28
  def run_all
26
- all = Compat.matching_files(self, Dir.glob('{,**/}*.sc{,d}'))
27
- run_on_modifications(all)
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 run_sclang(paths)
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
- got_status, exit_status = _run_cmd(cmd, title)
82
+ run_status, exit_status = _run_cmd(cmd, title)
68
83
 
69
- unless got_status
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
- got_status = false
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
- status, msg, line = _check_line_for_status(line)
101
- if status
102
- got_status = true
103
- Compat::UI.notify(msg, title: title, image: status)
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
- [got_status, exit_status]
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 == 0 ? :success : :failed
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
@@ -1,5 +1,5 @@
1
1
  module Guard
2
2
  module SclangVersion
3
- VERSION = '0.1.0'
3
+ VERSION = '0.3.0'
4
4
  end
5
5
  end
@@ -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.removeExtension;
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.1.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: 2017-12-29 00:00:00.000000000 Z
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.8
138
+ rubygems_version: 2.7.6
126
139
  signing_key:
127
140
  specification_version: 4
128
141
  summary: Guard gem for running sclang commands
@@ -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