seeing_is_believing 3.0.0.beta.7 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 866178b03727394e7c24c5cfbaa48ea4edbca4e1
4
- data.tar.gz: cfe4540e781ec9aa65b79a950d8760058136a85d
3
+ metadata.gz: c0318721dea2259939dac9f239eaf465f9a7d605
4
+ data.tar.gz: a9c3681770369df1da596a736c266ff51624603e
5
5
  SHA512:
6
- metadata.gz: 514947858dab6b669eeb25f8b729e330d9435b438f2821073a56a12226451710a54f775415591e56c8673d071e276c102ec7ca001f4f6f2ce03fe9d2f1282b7b
7
- data.tar.gz: 341dea9e96e9e1c57565254830f5f22648bcd2b9363d492b1a8718dddc54e30861c449d5374f3822e7ef7c88ce89ea107c79e5049c7e216a35a88c3b8440f735
6
+ metadata.gz: 06109b5b546f05c712f17d3856fb5faf8e41579a00758dd3fe05a4bec5dd12028a532c6429529db257a15aebfe4bee5a574999f714f0ac2e22ab1986eafc267c
7
+ data.tar.gz: 12f47cae8b1613713ec81bc66a7156d89ed15a967b8c1b3a54af4bdc520cb25541bf2327cadf452eef2da14f4cf35ec4cd103c4718a3319ecbd1bdc035e076a4
data/.travis.yml CHANGED
@@ -1,9 +1,8 @@
1
1
  language: ruby
2
- install: gem install bundler && bundle install --standalone --binstubs bundle/bin
2
+ before_install: gem install bundler
3
+ install: rake install
3
4
  script: bundle exec rake ci
4
5
  rvm:
5
- - 1.9.3
6
- - 2.0.0
7
6
  - 2.1.2
8
7
  - 2.2.0
9
- - 2.3.0
8
+ - 2.3.1
data/Gemfile CHANGED
@@ -1,2 +1,3 @@
1
1
  source 'http://rubygems.org'
2
2
  gemspec
3
+ gem 'pry'
data/Rakefile CHANGED
@@ -1,9 +1,14 @@
1
- require 'bundler'
2
-
3
1
  desc 'Have Bundler setup a standalone environment -- run tests in this, b/c its faster and safer'
4
2
  task :install do
5
- # Running without rubygems # http://myronmars.to/n/dev-blog/2012/03/faster-test-boot-times-with-bundler-standalone
6
- sh 'bundle install --standalone --binstubs bundle/bin'
3
+ `which bundle`
4
+ unless $?.success?
5
+ sh 'gem', 'install', 'bundler'
6
+ end
7
+
8
+ unless Dir.exist? 'bundle'
9
+ # Running without rubygems # http://myronmars.to/n/dev-blog/2012/03/faster-test-boot-times-with-bundler-standalone
10
+ sh 'bundle', 'install', '--standalone', '--binstubs', 'bundle/bin'
11
+ end
7
12
  end
8
13
 
9
14
  desc 'Remove generated and irrelevant files'
@@ -24,12 +29,19 @@ end
24
29
 
25
30
  desc 'Run specs'
26
31
  task spec: :bundle do
27
- sh 'ruby', '--disable-gem', *Bundler.load.specs.flat_map(&:full_require_paths).flat_map { |p| ['-I', p ] }, '-S', 'bundle/bin/mrspec'
32
+ require 'bundler'
33
+ sh 'ruby', '--disable-gem',
34
+ *Bundler.load.specs.flat_map(&:full_require_paths).flat_map { |p| ['-I', p ] },
35
+ '-S', 'bundle/bin/mrspec'
28
36
  end
29
37
 
30
38
  desc 'Run cukes'
31
39
  task cuke: :bundle do
32
- sh 'ruby', '--disable-gem', *Bundler.load.specs.flat_map(&:full_require_paths).flat_map { |p| ['-I', p ] }, '-S', 'bundle/bin/cucumber', '--tags', '~@not-implemented'
40
+ require 'bundler'
41
+ sh 'ruby', '--disable-gem',
42
+ *Bundler.load.specs.flat_map(&:full_require_paths).flat_map { |p| ['-I', p ] },
43
+ '-S', 'bundle/bin/cucumber',
44
+ '--tags', '~@not-implemented'
33
45
  end
34
46
 
35
47
  desc 'Run all specs and cukes'
data/Readme.md CHANGED
@@ -6,17 +6,34 @@ Seeing Is Believing
6
6
 
7
7
  Evaluates Ruby code, recording the results of each line.
8
8
  Integrates with any extensible editor (I've integrated it with many already, see [the list](https://github.com/JoshCheek/seeing_is_believing#editor-integration)).
9
+ If you like Swift Playgrounds, you'll like SiB.
9
10
 
10
11
  ![example](https://s3.amazonaws.com/josh.cheek/images/scratch/sib-example1.gif)
11
12
 
12
13
  Watch a [longer video](http://vimeo.com/73866851).
13
14
 
14
- Works in Ruby 1.9, 2.0, 2.1, 2.2, rubinius (I **think**, need to make better tests), still trying to get it working with Jruby.
15
+
16
+ Install
17
+ =======
18
+
19
+ Requires Ruby >= 2.1
20
+
21
+ ```sh
22
+ $ gem install seeing_is_believing
23
+ ```
24
+
25
+ Verify the install with
26
+
27
+ ```sh
28
+ $ seeing_is_believing -e '1 + 1'
29
+ 1 + 1 # => 2
30
+ ```
31
+
15
32
 
16
33
  Use The Binary
17
34
  ==============
18
35
 
19
- `cat simple_example.rb`
36
+ Given the file `simple_example.rb`
20
37
 
21
38
  ```ruby
22
39
  5.times do |i|
@@ -24,25 +41,29 @@ Use The Binary
24
41
  end
25
42
  ```
26
43
 
27
- `seeing_is_believing simple_example.rb`
44
+ `$ seeing_is_believing simple_example.rb` will print:
45
+
28
46
  ```ruby
47
+
29
48
  5.times do |i| # => 5
30
49
  i * 2 # => 0, 2, 4, 6, 8
31
50
  end # => 5
32
51
  ```
33
52
 
53
+
34
54
  Use The Lib
35
55
  ===========
36
56
 
37
57
  ```ruby
38
58
  require 'seeing_is_believing'
39
- believer = SeeingIsBelieving.new("[:a, :b, :c].each do |i|
59
+
60
+ # There are a lot of options you can pass here, including a custom handler
61
+ handler = SeeingIsBelieving.call("[:a, :b, :c].each do |i|
40
62
  i.upcase
41
63
  end")
64
+ result = handler.result
42
65
 
43
- result = believer.call # => #<SIB::Result @results={1=>#<SIB:Line["[:a, :b, :c]"] no exception>, 2=>#<SIB:Line[":A", ":B", ":C"] no exception>, 3=>#<SIB:Line["[:a, :b, :c]"] no exception>}\n @stdout=""\n @stderr=""\n @exitstatus=0\n @bug_in_sib=nil>
44
-
45
- result[2] # => #<SIB:Line[":A", ":B", ":C"] no exception>
66
+ result[2] # => [":A", ":B", ":C"]
46
67
  result[2][0] # => ":A"
47
68
  result[2][1] # => ":B"
48
69
  result[2][2] # => ":C"
@@ -53,12 +74,6 @@ result.stderr # => ""
53
74
  result.exception # => nil
54
75
  ```
55
76
 
56
- Install
57
- =======
58
-
59
- Currently requires Ruby 1.9 or 2.x
60
-
61
- $ gem install seeing_is_believing
62
77
 
63
78
 
64
79
  Editor Integration
@@ -69,20 +84,44 @@ Editor Integration
69
84
  * [TextMate 1](https://github.com/JoshCheek/text_mate_1-seeing-is_believing)
70
85
  * [TextMate 2](https://github.com/JoshCheek/text_mate_2-seeing-is_believing) (TM2 is actually looking really nice these days -- Josh Cheek, 18 Feb 2015)
71
86
 
87
+
72
88
  Vim
73
- ===
89
+ ---
74
90
 
75
- I didn't write either of these, but they both support Seeing Is Believing. I've looked through the code, it works reasonably. One of them, I wound up having to edit the installed package, don't remember which.
91
+ These packages support SiB:
76
92
 
77
- * [vim-ruby-xmpfilter](https://github.com/t9md/vim-ruby-xmpfilter)
78
93
  * [vim-seeing-is-believing](https://github.com/hwartig/vim-seeing-is-believing)
94
+ * [vim-ruby-xmpfilter](https://github.com/t9md/vim-ruby-xmpfilter)
95
+
96
+ Personally, I had difficulty with them, but this configuration has gotten me pretty far:
97
+
98
+ ```viml
99
+ " ===== Seeing Is Believing =====
100
+ " Assumes you have a Ruby with SiB available in the PATH
101
+ " If it doesn't work, you may need to `gem install seeing_is_believing -v 3.0.0.beta.6`
102
+ " ...yeah, current release is a beta, which won't auto-install
103
+
104
+ " Annotate every line
105
+ nmap <leader>b :%!seeing_is_believing --timeout 12 --line-length 500 --number-of-captures 300 --alignment-strategy chunk<CR>;
106
+ " Annotate marked lines
107
+ nmap <leader>n :%.!seeing_is_believing --timeout 12 --line-length 500 --number-of-captures 300 --alignment-strategy chunk --xmpfilter-style<CR>;
108
+ " Remove annotations
109
+ nmap <leader>c :%.!seeing_is_believing --clean<CR>;
110
+ " Mark the current line for annotation
111
+ nmap <leader>m A # => <Esc>
112
+ " Mark the highlighted lines for annotation
113
+ vmap <leader>m :norm A # => <Esc>
114
+ ```
115
+
79
116
 
80
117
  Emacs Integration
81
- =================
118
+ -----------------
82
119
 
83
120
  You can use my friend's configuration [file](https://github.com/jcinnamond/seeing-is-believing).
121
+ You can see him use it in [this](http://brightonruby.com/2016/the-point-of-objects-john-cinnamond/?utm_source=rubyweekly&utm_medium=email)
122
+ presentation at 10 minutes.
84
123
 
85
- Or, adding this function to your Emacs configuration will get you pretty far:
124
+ Alternatively, adding this function to your Emacs configuration will get you pretty far:
86
125
 
87
126
  ```scheme
88
127
  (defun seeing-is-believing ()
@@ -100,6 +139,13 @@ You can now call `seeing-is-believing` to replace the current region
100
139
  or current buffer contents with the output of running it through
101
140
  `seeing_is_believing`.
102
141
 
142
+
143
+ Features
144
+ ========
145
+
146
+ Check the [features](features) directory.
147
+
148
+
103
149
  Known Issues
104
150
  ============
105
151
 
@@ -108,15 +154,22 @@ Known Issues
108
154
  This code will be wrapped. But using the value is **syntactically** invalid in Ruby, because it constitutes a "void value expression" (aka a pointless timesink and the cause of many bugs in SiB).
109
155
  Unfortunately, I can't easily check it to seee if it's void since it's not in the parsed AST. But it's so edge that I don't think it's worth worrying about.
110
156
 
111
- Version 2
112
- =========
157
+ Setting up Development
158
+ ======================
113
159
 
114
- Feature complete, I'll fix bugs in it until version 3 is released, though
160
+ * Make sure you have Ruby (I use [chruby](https://github.com/postmodern/chruby) and [ruby-install](https://github.com/postmodern/ruby-install) for this).
161
+ * Make sure you have bundler and rake (`gem install bundler rake`)
162
+ * Fork the repo (there's a button on Github)
163
+ * Clone your fork (`git clone git@github.com:YOUR_GITHUB_NAME/seeing_is_believing.git`)
164
+ * Install the dependencies (`rake install`) This approach is painful, but it means the test suite is like 30s instead of 5min.
165
+ * Get a list of rake tasks (`rake -T`)
166
+ * Run the full test suite (`rake`)
167
+ * Run the rspec tests `bundle exec rspec` from here you can pass options you want, such as a tag for the tests you're interested in.
168
+ * Run the Cucumber tests `bundle exec cucumber` (these literally invoke the executable, as a user would)
115
169
 
116
- Version 3
117
- =========
118
170
 
119
- These need to be done before release:
171
+ Some stuff that might happen one day
172
+ ====================================
120
173
 
121
174
  * Add default to number of captures (1000), require user to explicitly set it to infinity
122
175
  * Expose markers via the CLI
@@ -127,10 +180,6 @@ These need to be done before release:
127
180
  rather than having to figure out all the compmlex ecosystem around installing
128
181
  * Would be nice to have real integration with Emacs
129
182
  * Would be nice to support Ruby Mine
130
-
131
- Version 4
132
- =========
133
-
134
183
  * How about if begin/rescue/end was able to record the result on the rescue section
135
184
  * How about if you could configure which kinds of results you were interested in
136
185
  (e.g. turn on/off recording of method definitions, and other results)
@@ -145,6 +194,8 @@ Version 4
145
194
  Could have fallback strategies, so e.g. `-s min=40,fallback=line`
146
195
  * Package Ruby with the editor downloads so that they don't require you to know so fkn much to set it up.
147
196
  * Allow user to set marker
197
+ * Maybe rename xmpfilter style, not many people know what that is, so the name doesn't help users
198
+
148
199
 
149
200
  Inspiration
150
201
  ===========
@@ -153,10 +204,6 @@ Inspiration
153
204
  * Bret Victor's completely inspiring talk [Inventing on Principle](https://www.youtube.com/watch?v=PUv66718DII).
154
205
  * My 8th Light mentor, [Doug Bradbury](http://blog.8thlight.com/doug-bradbury/archive.html) who asked me to make it for his Kids Ruby sessions (I don't think we ever finished integrating it, though >.<)
155
206
 
156
- Interestingly, [Swift playground](https://www.youtube.com/watch?v=oY6nQS3MiF8&t=25m51s)
157
- are very similar (though better integrated since they cerce you into using xcode).
158
- Released about a year and a half before them, but maybe I should take advantage of
159
- their marketing anyway: Swift Playgrounds for Ruby!! :P
160
207
 
161
208
  Shout outs
162
209
  ==========
@@ -258,8 +258,6 @@ Feature: Running the binary successfully
258
258
  """
259
259
  And the exit status is 0
260
260
 
261
-
262
- @not-implemented
263
261
  Scenario: Fork records data in parent and child, parent exec does not affect it.
264
262
  Given the file "fork_exec_parent.rb":
265
263
  """
@@ -268,7 +266,7 @@ Feature: Running the binary successfully
268
266
  :parent
269
267
  exec 'echo', 'hello'
270
268
  else
271
- sleep 1
269
+ sleep 1 #
272
270
  :child
273
271
  end
274
272
  :child
@@ -283,15 +281,14 @@ Feature: Running the binary successfully
283
281
  :parent # => :parent
284
282
  exec 'echo', 'hello'
285
283
  else
286
- sleep 1 # => 1
284
+ sleep 1 #
287
285
  :child # => :child
288
- end
286
+ end # => :child
289
287
  :child # => :child
290
288
 
291
289
  # >> hello
292
290
  """
293
291
 
294
- @not-implemented
295
292
  Scenario: Fork records data in parent and child, child exec does not affect it.
296
293
  Given the file "fork_exec_child.rb":
297
294
  """
@@ -317,7 +314,7 @@ Feature: Running the binary successfully
317
314
  else
318
315
  :child # => :child
319
316
  exec 'echo', 'hello'
320
- end
317
+ end # => :parent
321
318
  :parent # => :parent
322
319
 
323
320
  # >> hello
@@ -123,7 +123,12 @@ class SeeingIsBelieving
123
123
  self.help_screen = Binary.help_screen_extended(markers)
124
124
 
125
125
  when '-g', '--debug'
126
- self.debug = true
126
+ self.debug = true
127
+
128
+ when '--debug-to'
129
+ next_arg.call arg, "a filename" do |filename|
130
+ self.debug = filename
131
+ end
127
132
 
128
133
  when '-d', '--line-length'
129
134
  extract_positive_int_for.call arg do |n|
@@ -237,10 +242,14 @@ class SeeingIsBelieving
237
242
  lib_options.event_handler = EventStream::Handlers::StreamJsonEvents.new(stdout)
238
243
  end
239
244
 
240
- if debug?
241
- self.debugger = Debugger.new stream: stderr, colour: true
242
- self.lib_options.debugger = debugger
245
+ case debug
246
+ when String
247
+ debug_file = File.open(debug, 'a').tap { |f| f.sync = true }
248
+ self.debugger = Debugger.new stream: debug_file, colour: false
249
+ when true
250
+ self.debugger = Debugger.new stream: stderr, colour: stderr.tty?
243
251
  end
252
+ self.lib_options.debugger = debugger
244
253
 
245
254
  if filename && body
246
255
  add_error("Cannot give a program body and a filename to get the program body from.")
@@ -11,6 +11,7 @@
11
11
  # read the wrong file... of course, since we rewrite the file,
12
12
  # its body will be incorrect, anyway.
13
13
 
14
+ require 'rbconfig'
14
15
  require 'timeout'
15
16
  require 'seeing_is_believing/error'
16
17
  require 'seeing_is_believing/result'
@@ -74,9 +75,11 @@ class SeeingIsBelieving
74
75
  end
75
76
 
76
77
  def set_back_to_initial_conditions
77
- @was_backed_up ?
78
- File.rename(backup_filename, filename) :
78
+ if @was_backed_up
79
+ File.rename(backup_filename, filename)
80
+ else
79
81
  File.delete(filename)
82
+ end
80
83
  end
81
84
 
82
85
  def write_program_to_file
@@ -97,32 +100,33 @@ class SeeingIsBelieving
97
100
  # setup environment variables
98
101
  env = ENV.to_hash.merge 'SIB_VARIABLES.MARSHAL.B64' =>
99
102
  [Marshal.dump(
100
- event_stream_fd: child_eventstream.to_i,
103
+ event_stream_fd: 4,
101
104
  max_line_captures: max_line_captures,
102
105
  num_lines: program.lines.count,
103
106
  filename: filename
104
107
  )].pack('m0')
105
108
 
106
109
  # evaluate the code in a child process
107
- opts = { in: child_stdin,
108
- out: child_stdout,
109
- err: child_stderr,
110
- child_eventstream => child_eventstream }
111
- child = Process.detach Kernel.spawn(env, *popen_args, opts)
110
+ opts = {
111
+ 4 => child_eventstream,
112
+ in: child_stdin,
113
+ out: child_stdout,
114
+ err: child_stderr,
115
+ pgroup: true, # run it in its own process group so we can SIGINT the whole group
116
+ }
117
+ child_pid = Kernel.spawn(env, *popen_args, opts)
118
+ child_pgid = Process.getpgid(child_pid)
112
119
 
113
120
  # close child streams b/c they won't emit EOF
114
121
  # until both child and parent references are closed
115
- child_eventstream.close
116
- child_stdout.close
117
- child_stderr.close
118
- child_stdin.close
122
+ close_streams(child_eventstream, child_stdout, child_stderr, child_stdin)
119
123
  stdin.sync = true
120
124
 
121
- # send stdin
122
- Thread.new {
125
+ # send stdin (char at a time b/c input could come from a stream)
126
+ Thread.new do
123
127
  provided_input.each_char { |char| stdin.write char }
124
128
  stdin.close
125
- }
129
+ end
126
130
 
127
131
  # set up the event consumer
128
132
  consumer = EventStream::Consumer.new(events: eventstream, stdout: stdout, stderr: stderr)
@@ -130,16 +134,17 @@ class SeeingIsBelieving
130
134
 
131
135
  # wait for completion
132
136
  Timeout.timeout timeout_seconds do
133
- exitstatus = child.value.exitstatus
134
- consumer.process_exitstatus exitstatus
137
+ Process.wait child_pid
138
+ consumer.process_exitstatus($?.exitstatus)
135
139
  consumer_thread.join
136
140
  end
137
141
  rescue Timeout::Error
138
- Process.kill "KILL", child.pid
139
142
  consumer.process_timeout timeout_seconds
140
- consumer_thread.join # finish consuming events
141
143
  ensure
142
- [stdin, stdout, stderr, eventstream].each { |io| io.close unless io.closed? }
144
+ allow_error(Errno::ESRCH) { Process.kill "-INT", child_pgid } # negative makes it apply to the group
145
+ allow_error(Errno::ECHILD) { Process.wait child_pid } # I can't tell if this actually works, or just creates enough of a delay for the OS to finish cleaning up the thread
146
+ consumer_thread.join
147
+ close_streams(stdin, stdout, stderr, eventstream)
143
148
  end
144
149
 
145
150
  def popen_args
@@ -151,5 +156,14 @@ class SeeingIsBelieving
151
156
  *require_flags, # users can inject files to be required
152
157
  filename]
153
158
  end
159
+
160
+ def allow_error(error)
161
+ yield
162
+ rescue error
163
+ end
164
+
165
+ def close_streams(*streams)
166
+ streams.each { |io| io.close unless io.closed? }
167
+ end
154
168
  end
155
169
  end