sumbach / seeing_is_believing

Displays the results of every line of code in your file

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Stories in Ready Build Status

Seeing Is Believing

Evaluates Ruby code, recording the results of each line. Integrates with any extensible editor (I've integrated it with many already, see the list). If you like Swift Playgrounds, you'll like SiB.

example

Watch a longer video.

Install

Requires Ruby >= 2.1

$ gem install seeing_is_believing

Verify the install with

$ seeing_is_believing -e '1 + 1'
1 + 1  # => 2

Use The Binary

Given the file simple_example.rb

5.times do |i|
  i * 2
end

$ seeing_is_believing simple_example.rb will print:

5.times do |i|  # => 5
  i * 2         # => 0, 2, 4, 6, 8
end             # => 5

$ seeing_is_believing simple_example.rb --json will print:

{"stdout":"","stderr":"","exitstatus":0,"exception":null,"lines":{"1":["5"],"2":["0","2","4","6","8"],"3":["5"]}}

Protips

These things have been useful for integrating.

If you want to execute from some specific dir (eg if your editor is in the wrong dir) try using Dir.chdir at the top of the script. Eg I used that here so I could run with a full Rails app available in "Completely against the real env".

If you want some specific file to be available in that environment, require the fullpath to the file. Eg I used that here to load up the Rils schema in "Running against the real schema".

You can also set the $LOAD_PATH to a gem you're working on and then require files as if it was installed.

You work with gets by setting $stdin to the DATA segment and writing inputs there.

$stdin = DATA

puts "What's your name?"
name = gets.chomp
puts "What's your favourite colour?"
colour = gets.chomp
puts "#{name}'s favourite colour is #{colour}."

# >> What's your name?
# >> What's your favourite colour?
# >> Josh's favourite colour is brown.

__END__
Josh
brown

Rescue lines you expect to explode so that it displays the expected result and continues evaluating.

lambda { |x| x }.call()     rescue $!  # => #<ArgumentError: wrong number of arguments (given 0, expected 1)>
lambda { |x| x }.call(1)               # => 1
lambda { |x| x }.call(1, 2) rescue $!  # => #<ArgumentError: wrong number of arguments (given 2, expected 1)>

Use fork to look at what a program does when run two different ways.

class A
  fork && raise("omg")  # => nil
rescue
  $!                    # => #<RuntimeError: omg>
else
  :nothing_raised       # => :nothing_raised
end                     # => #<RuntimeError: omg>, :nothing_raised

Use The Lib

require 'seeing_is_believing'

# There are a lot of options you can pass here, including a custom handler
handler = SeeingIsBelieving.call("[:a, :b, :c].each do |i|
                                    i.upcase
                                  end")
result = handler.result

result[2]            # => [":A", ":B", ":C"]
result[2][0]         # => ":A"
result[2][1]         # => ":B"
result[2][2]         # => ":C"
result[2].join(", ") # => ":A, :B, :C"

result.stdout    # => ""
result.stderr    # => ""
result.exception # => nil

Editor Integration

  • Atom (prob has best installation instructions, overall best integration, but config and filesystem events are iffy)
  • Sublime 2 and 3 (works reasonably, but isn't integrated with the package manager)
  • TextMate 1
  • TextMate 2 (TM2 is actually looking really nice these days -- Josh Cheek, 18 Feb 2015)

Vim

These packages support SiB:

Personally, I had difficulty with them, but this configuration has gotten me pretty far:

" ===== Seeing Is Believing =====
" Assumes you have a Ruby with SiB available in the PATH
" If it doesn't work, you may need to `gem install seeing_is_believing -v 3.0.0.beta.6`
" ...yeah, current release is a beta, which won't auto-install

" Annotate every line
  nmap <leader>b :%!seeing_is_believing --timeout 12 --line-length 500 --number-of-captures 300 --alignment-strategy chunk<CR>;
" Annotate marked lines
  nmap <leader>n :%.!seeing_is_believing --timeout 12 --line-length 500 --number-of-captures 300 --alignment-strategy chunk --xmpfilter-style<CR>;
" Remove annotations
  nmap <leader>c :%.!seeing_is_believing --clean<CR>;
" Mark the current line for annotation
  nmap <leader>m A # => <Esc>
" Mark the highlighted lines for annotation
  vmap <leader>m :norm A # => <Esc>

Emacs Integration

You can use my friend's configuration file. You can see him use it in this presentation at 10 minutes.

Alternatively, adding this function to your Emacs configuration will get you pretty far:

(defun seeing-is-believing ()
  "Replace the current region (or the whole buffer, if none) with the output
of seeing_is_believing."
  (interactive)
  (let ((beg (if (region-active-p) (region-beginning) (point-min)))
        (end (if (region-active-p) (region-end) (point-max)))
        (origin (point)))
    (shell-command-on-region beg end "seeing_is_believing" nil 'replace)
    (goto-char origin)))

You can now call seeing-is-believing to replace the current region or current buffer contents with the output of running it through seeing_is_believing.

Features

Check the features directory.

Known Issues

  • begin; else; break; end this code (an else without a resecue) will emit a warning in Ruby, and is omitted from Parser's AST. As such, I doubt that anyone will ever write it. But if you were to write it, it would blow up, because SiB rewrites your code, wrapping every expression that could have a value. 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). 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.

Setting up Development

  • Make sure you have Ruby (I use chruby and ruby-install for this).
  • Make sure you have bundler and rake (gem install bundler rake)
  • Fork the repo (there's a button on Github)
  • Clone your fork (git clone git@github.com:YOUR_GITHUB_NAME/seeing_is_believing.git)
  • Install the dependencies (rake install) This approach is painful, but it means the test suite is like 30s instead of 5min.
  • Get a list of rake tasks (rake -T)
  • Run the full test suite (rake)
  • 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.
  • Run the Cucumber tests bundle exec cucumber (these literally invoke the executable, as a user would)

Some stuff that might happen one day

  • Add default to number of captures (1000), require user to explicitly set it to infinity
  • Expose markers via the CLI
  • Spruce up editor integration
    • Integrate with package managers where they are available
    • Expose options to use the streaming API (update as events are seen)
    • Ship with Traveling Ruby so that new users can just press a button and it works, rather than having to figure out all the compmlex ecosystem around installing
    • Would be nice to have real integration with Emacs
    • Would be nice to support Ruby Mine
  • How about if begin/rescue/end was able to record the result on the rescue section
  • How about if you could configure which kinds of results you were interested in (e.g. turn on/off recording of method definitions, and other results)
  • What about recording the result of a line inside of a string interpolation, e.g. "a#{\n1\n}b" could record line 2 is 1 and line 3 is "a\n1\nb" This would require smarter annotators.
  • Allow debugger to take a filename (ie debug to a file insteaad of to stderr)
  • --cd dir cd to that dir before executing the code
  • --cd - cd to the dir of the file being executed before executing it
  • --only-show-lines output only on specified lines (doesn't change stdout/stderr/exceptions)
  • More alignment strategies e.g. min=40 would align to 40, unless that was too short. Could have fallback strategies, so e.g. -s min=40,fallback=line
  • Package Ruby with the editor downloads so that they don't require you to know so fkn much to set it up.
  • Allow user to set marker
  • Maybe rename xmpfilter style, not many people know what that is, so the name doesn't help users

Inspiration

Shout outs

  • Whitequark for all the work on Parser, which dramatically dramatically improved SiB (I used to have my own horribly shitty line-based parser)
  • Travis CI... I love you times a million! So many difficult bugs have been caught by this. It's so easy to work with, astoundingly convenient, helps me guarantee that SiB works on everyone else's computers, too. And it's free since SiB is open source. I literally have a Travis CI sticker on my laptop, I love you that much.

License

WTFPL

Copyright (C) 2014 Josh Cheek <josh.cheek@gmail.com>

This program is free software. It comes without any warranty,
to the extent permitted by applicable law.
You can redistribute it and/or modify it under the terms of the
Do What The Fuck You Want To Public License,
Version 2, as published by Sam Hocevar.
See http://www.wtfpl.net/ for more details.

About

Displays the results of every line of code in your file


Languages

Language:Ruby 85.4%Language:Gherkin 14.6%