nyan 0.0.1

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.
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ .rvmrc
4
+ Gemfile.lock
5
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in nyan_formatter.gemspec
4
+ gemspec
@@ -0,0 +1,6 @@
1
+ guard 'rspec', :version => 2 do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec" }
5
+ end
6
+
@@ -0,0 +1,80 @@
1
+ Nyan ![travis-ci](https://secure.travis-ci.org/textgoeshere/nyan.png)
2
+ ==================
3
+
4
+ Your favourite aging meme is reheated as an RSpec custom formatter.
5
+
6
+ For entertainment purposes only.
7
+
8
+ FAQ
9
+ ---
10
+
11
+ * Didn't this meme jump the shark, like, ages ago?
12
+
13
+ Yes.
14
+
15
+ * It's got no tail
16
+
17
+ Look closer.
18
+
19
+ * It's got no feet!
20
+
21
+ LOOK CLOSER.
22
+
23
+ * It's really slow
24
+
25
+ Write faster specs.
26
+
27
+ * It's still really slow
28
+
29
+ Send me a pull request where the animation runs in a separate thread.
30
+
31
+ * The colours are all wrong
32
+
33
+ Probably need a new graphics card or something.
34
+
35
+ Requirements
36
+ ------------
37
+
38
+ * RSpec 2 (tested against RSpec 2.6)
39
+
40
+ Install
41
+ -------
42
+
43
+ Add to your `Gemfile` (usually inside your `:test` group):
44
+
45
+ gem "nyan"
46
+
47
+ Alternatively install directly:
48
+
49
+ $ gem install nyan
50
+
51
+ Usage
52
+ -----
53
+
54
+ $ rspec spec -f Nyan::Formatter
55
+
56
+ Or if you want the joy of Nyan without running specs, use the binary:
57
+
58
+ $ nyan
59
+
60
+ Your terminal should be at least 180 columns x 50 rows.
61
+
62
+ Development
63
+ -----------
64
+
65
+ * Source hosted at [GitHub](https://github.com/kapoq/nyan)
66
+ * Report issues/Questions/Feature requests on [GitHub Issues](https://github.com/kapoq/nyan)
67
+ * CI at [Travis](http://travis-ci.org/#!/textgoeshere/nyan)
68
+
69
+ Pull requests are very welcome! Make sure your patches are well tested. Please create a topic branch for every separate change
70
+ you make.
71
+
72
+ Testing
73
+ -------
74
+
75
+ $ rake
76
+
77
+ Author
78
+ ------
79
+
80
+ [Dave Nolan](https://github.com/textgoeshere)
@@ -0,0 +1,7 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ nyan_dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ $LOAD_PATH.unshift(nyan_dir) unless $LOAD_PATH.include?(nyan_dir)
4
+ require "nyan"
5
+
6
+ print cls
7
+ flight = Nyan::Flight.new
8
+ loop do
9
+ flight.next!
10
+ end
11
+
@@ -0,0 +1,20 @@
1
+ require "nyan/version"
2
+
3
+ require "nyan/colour"
4
+ require "nyan/shape"
5
+ require "nyan/sprite"
6
+ require "nyan/stage"
7
+
8
+ require "nyan/flight"
9
+
10
+ module Nyan
11
+ BLOCK = "\u2588"
12
+ SPACE = "\x20"
13
+ NEWLINE = "\n"
14
+
15
+ require "nyan/sprites/rainbow"
16
+ require "nyan/sprites/cat_head"
17
+ require "nyan/sprites/pop_tart"
18
+ require "nyan/sprites/tail"
19
+ require "nyan/sprites/star"
20
+ end
@@ -0,0 +1,27 @@
1
+ require "ansi"
2
+ include ANSI::Code
3
+
4
+ module Nyan
5
+ module Colour
6
+ MAP = {
7
+ "#" => "#{bright}#{black}",
8
+ "b" => "#{dark}#{black}",
9
+ "R" => "#{bright}#{magenta}",
10
+ "p" => "#{dark}#{magenta}",
11
+ "2" => "#{bright}#{yellow}",
12
+ "`" => "#{dark}#{yellow}",
13
+ "o" => "#{bright}#{white}",
14
+ "_" => "#{bright}#{white}",
15
+ "." => "#{dark}#{white}",
16
+ "1" => "#{bright}#{red}",
17
+ "3" => "#{bright}#{green}",
18
+ "4" => "#{bright}#{blue}",
19
+ "5" => "#{bright}#{magenta}"
20
+ }
21
+
22
+ def self.colourize(char)
23
+ escape_codes = MAP.fetch(char, reset)
24
+ "#{escape_codes}#{Nyan::BLOCK}"
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,51 @@
1
+ module Nyan
2
+ class Flight
3
+ def initialize
4
+ @stage = Stage.new
5
+
6
+ @rainbow = Sprite.new(:x => 0, :y => 17, :z => 1, :frames => Nyan::Rainbow.to_frames)
7
+
8
+ @cat_head = Sprite.new(:x => Nyan::Rainbow::TOTAL_LENGTH - 2,
9
+ :y => 17,
10
+ :z => 100,
11
+ :frames => Nyan::CatHead.to_frames,
12
+ :animation => Proc.new do
13
+ @initial_x ||= @x
14
+ @initial_y ||= @y
15
+ case offset = [@x == @initial_x && :initial || :offset, @y == @initial_y && :initial || :offset]
16
+ when [:initial, :initial] then @y -= 2
17
+ when [:initial, :offset] then @x += 2
18
+ when [:offset, :offset] then @y += 2
19
+ when [:offset, :initial] then @x -= 2
20
+ end
21
+ end)
22
+
23
+ @pop_tart = Sprite.new(:x => @cat_head.x - 20,
24
+ :y => @cat_head.y - 2,
25
+ :z => @cat_head.z - 1,
26
+ :frames => Nyan::PopTart.to_frames)
27
+
28
+ @stage.add_sprite(@rainbow)
29
+ @stage.add_sprite(@cat_head)
30
+ @stage.add_sprite(@pop_tart)
31
+ @tick_time = Time.now
32
+ end
33
+
34
+ def next!
35
+ if rand > 0.85
36
+ speed = rand > 0.5 ? 2 : 5
37
+ star = Sprite.new(:x => @stage.width,
38
+ :y => rand(@stage.height - 11),
39
+ :z => 0,
40
+ :speed => speed,
41
+ :frames => Nyan::Star.to_frames,
42
+ :frame_index => rand(Nyan::Star.to_frames.length - 1),
43
+ :animation => Proc.new { self.x -= @options[:speed] })
44
+ @stage.add_sprite(star)
45
+ end
46
+ @stage.play!
47
+ loop until Time.now - @tick_time >= 0.09
48
+ @tick_time = Time.now
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,44 @@
1
+ require 'rspec/core/formatters/base_text_formatter'
2
+ require 'nyan'
3
+
4
+ module Nyan
5
+ class Formatter < RSpec::Core::Formatters::BaseTextFormatter
6
+ def initialize(*args)
7
+ super
8
+ @nyan_flight = Nyan::Flight.new
9
+ @still_passing = true
10
+ print cls
11
+ puts "Awaiting Nyan..."
12
+ end
13
+
14
+ def example_passed(_)
15
+ @nyan_flight.next! if @still_passing
16
+ end
17
+
18
+ def example_failed(example)
19
+ super
20
+ @output.print cls
21
+ @output.print move(0,0)
22
+ @output.puts red("NO NYAN FOR YOU")
23
+ @still_passing = false
24
+ end
25
+
26
+ def dump_failures
27
+ return if failed_examples.empty?
28
+ output.puts
29
+ output.puts "Failures:"
30
+ failed_examples.each_with_index do |example, index|
31
+ output.puts
32
+ dump_pending_example_fixed(example, index) || dump_failure(example, index)
33
+ dump_backtrace(example)
34
+ end
35
+ end
36
+
37
+ def dump_backtrace(example)
38
+ format_backtrace(example.execution_result[:exception].backtrace, example).each do |backtrace_info|
39
+ output.puts cyan(" # #{backtrace_info}")
40
+ end
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,16 @@
1
+ module Nyan
2
+ module Shape
3
+ attr_accessor :top, :bottom, :left, :right
4
+
5
+ def outside?(other_shape)
6
+ (right < other_shape.left) or
7
+ (top > other_shape.bottom) or
8
+ (left > other_shape.right) or
9
+ (bottom < other_shape.top)
10
+ end
11
+
12
+ def inside?(other_shape)
13
+ !outside(other_shape)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,60 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Nyan
3
+ class Sprite
4
+ include Shape
5
+
6
+ attr_accessor :x, :y, :z, :frames, :frame_index
7
+ attr_reader :blk
8
+
9
+ def initialize(options = {}, &blk)
10
+ @options = options
11
+ self.x = @options.fetch(:x, 0)
12
+ self.y = @options.fetch(:y, 0)
13
+ self.z = @options.fetch(:z, 0)
14
+ self.frames = @options.fetch(:frames, [])
15
+ self.frame_index = @options.fetch(:frame_index, 0)
16
+ @blk = blk || @options[:animation]
17
+ end
18
+
19
+ def frame
20
+ frames[frame_index]
21
+ end
22
+
23
+ def lines
24
+ frame.lines
25
+ end
26
+
27
+ def animate!
28
+ self.frame_index = (self.frame_index + 1) % frames.length
29
+ self.instance_eval(&blk) if blk
30
+ end
31
+
32
+ def height
33
+ @height ||= frame.lines.count
34
+ end
35
+
36
+ def width
37
+ @width ||= frame.lines.map { |l| l.chomp.unansi.length }.max
38
+ end
39
+
40
+ def top
41
+ y
42
+ end
43
+
44
+ def bottom
45
+ y + height
46
+ end
47
+
48
+ def left
49
+ x
50
+ end
51
+
52
+ def right
53
+ x + width
54
+ end
55
+
56
+ def <=>(other)
57
+ z <=> other.z
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,26 @@
1
+ module Nyan
2
+ module CatHead
3
+ SHAPE =<<EOF
4
+ # #
5
+ #.### ###.#
6
+ #....## ##...#
7
+ #__....############...__#
8
+ ___...#..........#..___
9
+ #__.................__#
10
+ #.....................#
11
+ #....o#.......o#....#
12
+ #....##.......##....#
13
+ #........b.b........#
14
+ #.p.......b.......p.#
15
+ #.p.b....b....b.p.#
16
+ #...b....b....b...#
17
+ #....bbbb.bbbb....#
18
+ ###...........###
19
+ ###########
20
+ EOF
21
+
22
+ def self.to_frames
23
+ @frames ||= Array(SHAPE)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,28 @@
1
+ module Nyan
2
+ module PopTart
3
+ SHAPE =<<-EOF
4
+ ooooooooooooooooooooooooooooo
5
+ o22222222222222222222222222222o
6
+ o222222ppppppppppppppppp22222222o
7
+ o22222ppppppRRRpppppppppppppppp222o
8
+ o22pppppppppRRRppppppppppppppppp22o
9
+ o22pppppRRRppRRRpppppppRRpppppppp222o
10
+ o222ppppRRRppppppppppppRppppppppp222o
11
+ o222pppppppppppppppppppRpppppppppp22o
12
+ o222ppppRRRppppppRRRppppppppppp222o
13
+ o222ppppRRRppppppRRRppppppppppp2222o
14
+ o22pppppppppppppppppppppppppppp22222o
15
+ o22ppppppppRRRpppppppppppppppppp2222o
16
+ o22ppppppppRRRppppppRRRppppppppp2222o
17
+ o22ppppppppRRRppppppRRRppppppppp2222o
18
+ o22pppppppppppppppppRRRpppppppppp222o
19
+ o222pppppppppppppppppppppppppppp2222o
20
+ o222222ppppppppppppppppp222222222222o
21
+ ooooooooooooooooooooooooooooooooooo
22
+ EOF
23
+
24
+ def self.to_frames
25
+ @fames ||= Array(SHAPE)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,45 @@
1
+ module Nyan
2
+ module Rainbow
3
+ BAND_HEIGHT = 3
4
+ BEND_LENGTH = 18
5
+ SECTIONS = 5
6
+
7
+ COLOURS = %w(1 2 3 4 5)
8
+ BLANK = ([Nyan::SPACE] * BEND_LENGTH).join
9
+
10
+ FRAME_HEIGHT = COLOURS.length * BAND_HEIGHT + 1
11
+ FRAME_WIDTH = SECTIONS * BEND_LENGTH
12
+
13
+ TOTAL_LENGTH = SECTIONS * BEND_LENGTH
14
+ TOTAL_HEIGHT = BAND_HEIGHT * COLOURS.length
15
+
16
+ SLICE = COLOURS.each_with_object([]) do |colour, slice|
17
+ BAND_HEIGHT.times do
18
+ slice << "#{colour}" * BEND_LENGTH
19
+ end
20
+ end
21
+
22
+ def self.frame(is_peak = true)
23
+ frame_rows = Array.new(FRAME_HEIGHT + 1) { String.new }
24
+
25
+ SECTIONS.times do
26
+ this_slice = SLICE.dup
27
+ FRAME_HEIGHT.times do |i|
28
+ this_row = if (is_peak && i == FRAME_HEIGHT - 1) or (!is_peak && i == 0)
29
+ BLANK
30
+ else
31
+ this_slice.shift
32
+ end
33
+ frame_rows[i] << this_row
34
+ end
35
+ is_peak = !is_peak
36
+ end
37
+
38
+ frame_rows.join(NEWLINE)
39
+ end
40
+
41
+ def self.to_frames
42
+ @frames ||= [frame(true), frame(false)]
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,81 @@
1
+ module Nyan
2
+ module Star
3
+ SHAPE_LIST =<<EOF
4
+ ...........
5
+ ...........
6
+ ...........
7
+ ...........
8
+ ...........
9
+ .....X.....
10
+ ...........
11
+ ...........
12
+ ...........
13
+ ...........
14
+ ...........
15
+ --
16
+ ...........
17
+ ...........
18
+ ...........
19
+ ...........
20
+ .....X.....
21
+ ....X.X....
22
+ .....X.....
23
+ ...........
24
+ ...........
25
+ ...........
26
+ ...........
27
+ --
28
+ ...........
29
+ ...........
30
+ ...........
31
+ .....X.....
32
+ .....X.....
33
+ ...XX.XX...
34
+ .....X.....
35
+ .....X.....
36
+ ...........
37
+ ...........
38
+ ...........
39
+ --
40
+ ...........
41
+ .....X.....
42
+ .....X.....
43
+ .....X.....
44
+ ...........
45
+ .XXX.X.XXX.
46
+ ...........
47
+ .....X.....
48
+ .....X.....
49
+ .....X.....
50
+ ...........
51
+ --
52
+ ...........
53
+ ....XXX....
54
+ ...X...X...
55
+ .X.......X.
56
+ X.........X
57
+ X.........X
58
+ X.........X
59
+ .X.......X.
60
+ ..X.....X..
61
+ ....XXX....
62
+ ...........
63
+ --
64
+ .....X.....
65
+ ...........
66
+ ...........
67
+ ...........
68
+ ...........
69
+ X.........X
70
+ ...........
71
+ ...........
72
+ ...........
73
+ ...........
74
+ .....X.....
75
+ EOF
76
+
77
+ def self.to_frames
78
+ @frames ||= SHAPE_LIST.gsub(/\./, SPACE).gsub(/X/, BLOCK).split(/--./m)
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,27 @@
1
+ module Nyan
2
+ module Tail
3
+ SHAPE_LIST =<<-EOF
4
+ ..................
5
+ ..................
6
+ ..................
7
+ ..................
8
+ ..................
9
+ --
10
+ ..................
11
+ ..................
12
+ ..................
13
+ ..................
14
+ ..................
15
+ --
16
+ ..................
17
+ ..................
18
+ ..................
19
+ ..................
20
+ ..................
21
+ EOF
22
+
23
+ def self.to_frames
24
+ @frames ||= SHAPE_LIST.gsub(/\./, SPACE).gsub(/X/, BLOCK).split(/--./m)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,109 @@
1
+ module Nyan
2
+ class Stage
3
+ include Shape
4
+
5
+ SPACE = "\x20"
6
+ NOTHING = ""
7
+
8
+ attr_reader :output, :height, :width
9
+
10
+ def initialize(options = {})
11
+ @output = options.fetch(:output, $stdout)
12
+ @height = options.fetch(:height, ANSI::Terminal.terminal_height)
13
+ @width = options.fetch(:width, ANSI::Terminal.terminal_width)
14
+ @coloured = options.fetch(:coloured, true)
15
+ clear_buffer
16
+ end
17
+
18
+ def sprites
19
+ @sprites ||= []
20
+ end
21
+
22
+ def add_sprite(sprite)
23
+ self.sprites.push(sprite)
24
+ end
25
+
26
+ def remove_sprite(sprite)
27
+ self.sprites.delete(sprite)
28
+ end
29
+
30
+ def play!
31
+ render
32
+ animate!
33
+ clean!
34
+ end
35
+
36
+ def render
37
+ clear_buffer
38
+ sprites.sort.each { |s| write_to_buffer(s) }
39
+ print_buffer
40
+ end
41
+
42
+ def animate!
43
+ sprites.each { |s| s.animate! }
44
+ end
45
+
46
+ def clean!
47
+ sprites.delete_if { |s| s.outside?(self) }
48
+ end
49
+
50
+ def top
51
+ 0
52
+ end
53
+
54
+ def bottom
55
+ height - 1
56
+ end
57
+
58
+ def left
59
+ 0
60
+ end
61
+
62
+ def right
63
+ width - 1
64
+ end
65
+
66
+ def coloured?
67
+ @coloured
68
+ end
69
+
70
+ private
71
+
72
+ def clear_buffer
73
+ @buffer = Array.new(height) do
74
+ Array.new(width) do
75
+ { :char => SPACE, :colourized_char => SPACE }
76
+ end
77
+ end
78
+ end
79
+
80
+ def write_to_buffer(sprite)
81
+ sprite.lines.each_with_index do |line, i|
82
+ line_y = sprite.y + i
83
+ previous_colourized_char = nil
84
+ if line_y.between?(top, bottom)
85
+ line.chomp.chars.each_with_index do |char, j|
86
+ char_x = sprite.x + j
87
+ if char_x.between?(left, right) && char != Nyan::SPACE
88
+ colourized_char = Colour.colourize(char)
89
+ colourized_char = Nyan::BLOCK if colourized_char == previous_colourized_char
90
+ @buffer[line_y][char_x] = { :char => char, :colourized_char => colourized_char }
91
+ previous_colourized_char = colourized_char
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+
98
+ def print_buffer
99
+ key = coloured? ? :colourized_char : :char
100
+ @buffer.each_with_index do |row, i|
101
+ output.print move(i, 0)
102
+ output.print clear_line
103
+ output.print reset
104
+ output.print row.map { |h| h[key] }.join
105
+ output.print "\n" unless i == bottom
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,3 @@
1
+ module Nyan
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "nyan/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "nyan"
7
+ s.version = Nyan::VERSION
8
+ s.authors = ["dave@kapoq.com"]
9
+ s.email = ["dave@kapoq.com"]
10
+ s.homepage = "https://github.com/kapoq/nyan_formatter"
11
+ s.summary = "Nyan Cat flies across your terminal while your RSpec specs run!"
12
+ s.description = "Your favourite aging meme is reheated as an RSpec custom formatter. For entertainment purposes only. WARNING: enterprise-ready"
13
+
14
+ s.add_dependency "ansi"
15
+ s.add_dependency "rspec"
16
+
17
+ s.add_development_dependency "guard-rspec"
18
+ s.add_development_dependency "rake"
19
+ if RUBY_PLATFORM =~ /linux/
20
+ s.add_development_dependency "rb-inotify"
21
+ s.add_development_dependency "libnotify"
22
+ end
23
+
24
+ s.files = `git ls-files`.split("\n")
25
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
26
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
27
+ s.require_paths = ["lib"]
28
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nyan::Colour do
4
+ describe ".colourize" do
5
+ it "looks up the char in the map" do
6
+ Nyan::Colour::MAP.should_receive(:fetch).with("X", anything)
7
+ Nyan::Colour.colourize("X")
8
+ end
9
+
10
+ it "returns the escape code for the colour followed by a block char" do
11
+ Nyan::Colour::MAP.stub(:fetch => "__ESC__")
12
+ Nyan::Colour.colourize("X").should eql "__ESC__#{Nyan::BLOCK}"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ class SimpleShape
4
+ include ::Nyan::Shape
5
+
6
+ def initialize
7
+ @top, @bottom, @left, @right = [0, 0, 0, 0]
8
+ end
9
+ end
10
+
11
+ describe Nyan::Shape do
12
+ let(:shape) { SimpleShape.new }
13
+
14
+ describe "#outside?" do
15
+ let(:other_shape) { SimpleShape.new }
16
+
17
+ it "is outside when its right edge is beyond the left edge of the other shape" do
18
+ shape.right = other_shape.left - 1
19
+ shape.should be_outside(other_shape)
20
+ end
21
+
22
+ it "is outside when its left edge is beyond the right edge of the other shape" do
23
+ shape.left = other_shape.right + 1
24
+ shape.should be_outside(other_shape)
25
+ end
26
+
27
+ it "is outside when its top edge is below the bottom edge of the other shape" do
28
+ shape.top = other_shape.bottom + 1
29
+ shape.should be_outside(other_shape)
30
+ end
31
+
32
+ it "is outside when its bottom edge is above the top edge of the other shape" do
33
+ shape.bottom = other_shape.top - 1
34
+ shape.should be_outside(other_shape)
35
+ end
36
+
37
+ it "is not outside when its edges are all within the edges of the other shape" do
38
+ shape.should_not be_outside(other_shape)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,124 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nyan::Sprite do
4
+ let(:output) { StringIO.new }
5
+ let(:sprite) { Nyan::Sprite.new }
6
+ let(:frame1) { double(:frame1) }
7
+ let(:frame2) { double(:frame2) }
8
+ let(:frames) { [frame1, frame2] }
9
+
10
+ describe "#initialize" do
11
+ it "accepts optional x, y, and frames parameters and sets its instance variables to their values" do
12
+ sprite = Nyan::Sprite.new(:x => 1, :y => 2, :z => 3, :frames => frames, :frame_index => 4)
13
+ sprite.x.should == 1
14
+ sprite.y.should == 2
15
+ sprite.z.should == 3
16
+ sprite.frame_index.should == 4
17
+ sprite.frames.should == frames
18
+ end
19
+
20
+ describe "defaults" do
21
+ it "x = 0" do
22
+ sprite.x.should == 0
23
+ end
24
+
25
+ it "y = 0" do
26
+ sprite.y.should == 0
27
+ end
28
+
29
+ it "z = 0" do
30
+ sprite.z.should == 0
31
+ end
32
+
33
+ it "frames is an empty array" do
34
+ sprite.frames.should == []
35
+ end
36
+
37
+ it "frame_index = 0" do
38
+ sprite.frame_index.should == 0
39
+ end
40
+ end
41
+
42
+ it "accepts an block which is executed each animation step" do
43
+ sprite = Nyan::Sprite.new(:frames => frames) do
44
+ self.x = 99
45
+ end
46
+ sprite.should_receive(:x=).with(99)
47
+ sprite.animate!
48
+ end
49
+
50
+ it "accepts a Proc as an optional animation parameter which is executed each animation step" do
51
+ sprite = Nyan::Sprite.new(:frames => frames, :animation => Proc.new { self.x = 99 })
52
+ sprite.should_receive(:x=).with(99)
53
+ sprite.animate!
54
+ end
55
+
56
+ it "has left at x" do
57
+ sprite.x = 99
58
+ sprite.left.should == 99
59
+ end
60
+
61
+ it "has right at x + width" do
62
+ sprite.x = 99
63
+ sprite.stub(:width => 99)
64
+ sprite.right.should == 198
65
+ end
66
+
67
+ it "has top at y" do
68
+ sprite.y = 77
69
+ sprite.top.should == 77
70
+ end
71
+
72
+ it "has bottom at y + height" do
73
+ sprite.y = 77
74
+ sprite.stub(:height => 99)
75
+ sprite.bottom.should == 176
76
+ end
77
+ end
78
+
79
+ describe "frames" do
80
+ before do
81
+ sprite.frames = frames
82
+ end
83
+
84
+ describe "#frames" do
85
+ it "returns array of frames" do
86
+ sprite.frames.should eql frames
87
+ end
88
+ end
89
+
90
+ describe "#frame" do
91
+ it "returns the current frame" do
92
+ sprite.frame.should eql frame1
93
+ end
94
+ end
95
+
96
+ describe "#animate!" do
97
+ it "sets current frame to the next frame, looping to the start when necessary" do
98
+ sprite.frame_index = 1
99
+ sprite.animate!
100
+ sprite.frame.should eql frame1
101
+ end
102
+ end
103
+ end
104
+
105
+ it "has a height equal to the number of lines in the frame" do
106
+ sprite.frames = ["1\n2\n3\n4"]
107
+ sprite.height.should == 4
108
+ end
109
+
110
+ it "has a width equal to the number of characters in widest line of the frame excluding line breaks" do
111
+ sprite.frames = ["1\n22\n333\n22\n22"]
112
+ sprite.width.should == 3
113
+ end
114
+
115
+ describe "#<=>" do
116
+ let(:a) { double("Sprite a") }
117
+ let(:b) { double("Sprite b") }
118
+
119
+ it "sorts by z" do
120
+ a.should_receive(:<=>).with(b)
121
+ a <=> b
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,175 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nyan::Stage do
4
+ let(:output) { StringIO.new }
5
+ let(:stage) { Nyan::Stage.new(:output => output, :height => 5, :width => 5, :coloured => false) }
6
+ let(:sprite) { mock(:sprite) }
7
+
8
+ before do
9
+
10
+ end
11
+
12
+ describe "#initialize" do
13
+ context "when output parameter is present" do
14
+ it "sets output to the value of the output parameter" do
15
+ stage = Nyan::Stage.new(:output => output)
16
+ stage.output.should eql output
17
+ end
18
+ end
19
+
20
+ context "defaults" do
21
+ let(:default_stage) { Nyan::Stage.new }
22
+
23
+ it "sets output to $stdout" do
24
+ default_stage.output.should eql $stdout
25
+ end
26
+
27
+ it "is coloured" do
28
+ default_stage.should be_coloured
29
+ end
30
+
31
+ it "has a height equal to the terminal height" do
32
+ ::ANSI::Terminal.stub(:terminal_height => 99)
33
+ default_stage.height.should == 99
34
+ end
35
+
36
+ it "has a width equal to the terminal width" do
37
+ ::ANSI::Terminal.stub(:terminal_width => 99)
38
+ default_stage.width.should == 99
39
+ end
40
+
41
+ it "has top at 0" do
42
+ default_stage.top.should == 0
43
+ end
44
+
45
+ it "has left at 0" do
46
+ default_stage.left.should == 0
47
+ end
48
+
49
+ it "has right at width - 1" do
50
+ width = 99
51
+ default_stage.stub :width => width
52
+ default_stage.right.should == width - 1
53
+ end
54
+
55
+ it "has bottom at height - 1" do
56
+ height = 99
57
+ default_stage.stub :height => height
58
+ default_stage.bottom.should == height - 1
59
+ end
60
+ end
61
+ end
62
+
63
+ describe "#add_sprite" do
64
+ it "adds a sprite" do
65
+ stage.add_sprite(sprite)
66
+ stage.sprites.should include(sprite)
67
+ end
68
+ end
69
+
70
+ describe "#remove_sprite" do
71
+ it "removes a sprite" do
72
+ sprite1 = double(:sprite1)
73
+ sprite2 = double(:sprite2)
74
+ stage.add_sprite(sprite1)
75
+ stage.add_sprite(sprite2)
76
+ stage.remove_sprite(sprite1)
77
+ stage.sprites.should == [sprite2]
78
+ end
79
+ end
80
+
81
+ describe "#play!" do
82
+ it "renders, animates, and cleans" do
83
+ stage.should_receive(:render)
84
+ stage.should_receive(:animate!)
85
+ stage.should_receive(:clean!)
86
+ stage.play!
87
+ end
88
+ end
89
+
90
+ describe "#render" do
91
+ let(:sprites) { double("Sprites") }
92
+ let(:sprite) { Nyan::Sprite.new }
93
+
94
+ before do
95
+ stage.stub(:sprites => sprites)
96
+ sprites.stub(:sort => [sprite])
97
+ end
98
+
99
+ it "renders its sprites to its output in order of z-index" do
100
+ sprites.should_receive(:sort).and_return([])
101
+ stage.render
102
+ end
103
+
104
+ it "prints each sprite to the output" do
105
+ sprite.frames = %w(XXXX)
106
+ stage.render
107
+ output.string.should =~ /XXXX/
108
+ end
109
+
110
+ it "only prints characters within the viewport" do
111
+ stage.stub(:height => 1, :width => 1)
112
+ sprite.x = -1
113
+ sprite.y = -1
114
+ sprite.frames = ["OOO\nOXO\nOOO"]
115
+ stage.render
116
+ output.string.should =~ /X/
117
+ output.string.should_not =~ /O/
118
+ end
119
+
120
+ it "renders each sprite at its correct position" do
121
+ sprite.x = stage.right
122
+ sprite.y = stage.bottom
123
+ sprite.frames = %w(X)
124
+ stage.render
125
+ output.string.unansi.should =~ /X$/
126
+ end
127
+
128
+ context "when coloured" do
129
+ before do
130
+ stage.stub(:coloured? => true)
131
+ end
132
+
133
+ it "prints coloured chars" do
134
+ Nyan::Colour.stub(:colourize => "__COLOURED__")
135
+ sprite.frames = %w(x)
136
+ stage.render
137
+ output.string.should =~ /__COLOURED__/
138
+ end
139
+ end
140
+ end
141
+
142
+ describe "#clean!" do
143
+ before do
144
+ stage.stub(:sprites => [sprite])
145
+ end
146
+
147
+ it "checks whether the sprite is outside the stage" do
148
+ sprite.should_receive(:outside?).with(stage)
149
+ stage.clean!
150
+ end
151
+
152
+ it "removes sprites outside the stage" do
153
+ sprite.stub(:outside? => true)
154
+ stage.clean!
155
+ stage.sprites.should_not include(sprite)
156
+ end
157
+
158
+ it "does not remove sprites inside the stage" do
159
+ sprite.stub(:outside? => false)
160
+ stage.clean!
161
+ stage.sprites.should include(sprite)
162
+ end
163
+ end
164
+
165
+ describe "#animate!" do
166
+ before do
167
+ stage.add_sprite(sprite)
168
+ end
169
+
170
+ it "updates its sprites to their next frame" do
171
+ sprite.should_receive(:animate!)
172
+ stage.animate!
173
+ end
174
+ end
175
+ end
@@ -0,0 +1 @@
1
+ require 'nyan'
metadata ADDED
@@ -0,0 +1,141 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nyan
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - dave@kapoq.com
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-10-07 00:00:00.000000000 +02:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: ansi
17
+ requirement: &10658100 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *10658100
26
+ - !ruby/object:Gem::Dependency
27
+ name: rspec
28
+ requirement: &10657680 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: *10657680
37
+ - !ruby/object:Gem::Dependency
38
+ name: guard-rspec
39
+ requirement: &10657260 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: *10657260
48
+ - !ruby/object:Gem::Dependency
49
+ name: rake
50
+ requirement: &10705640 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: *10705640
59
+ - !ruby/object:Gem::Dependency
60
+ name: rb-inotify
61
+ requirement: &10705180 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: *10705180
70
+ - !ruby/object:Gem::Dependency
71
+ name: libnotify
72
+ requirement: &10704760 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: *10704760
81
+ description: ! 'Your favourite aging meme is reheated as an RSpec custom formatter.
82
+ For entertainment purposes only. WARNING: enterprise-ready'
83
+ email:
84
+ - dave@kapoq.com
85
+ executables:
86
+ - nyan.rb
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - .gitignore
91
+ - .rspec
92
+ - Gemfile
93
+ - Guardfile
94
+ - README.md
95
+ - Rakefile
96
+ - bin/nyan.rb
97
+ - lib/nyan.rb
98
+ - lib/nyan/colour.rb
99
+ - lib/nyan/flight.rb
100
+ - lib/nyan/formatter.rb
101
+ - lib/nyan/shape.rb
102
+ - lib/nyan/sprite.rb
103
+ - lib/nyan/sprites/cat_head.rb
104
+ - lib/nyan/sprites/pop_tart.rb
105
+ - lib/nyan/sprites/rainbow.rb
106
+ - lib/nyan/sprites/star.rb
107
+ - lib/nyan/sprites/tail.rb
108
+ - lib/nyan/stage.rb
109
+ - lib/nyan/version.rb
110
+ - nyan.gemspec
111
+ - spec/lib/colour_spec.rb
112
+ - spec/lib/shape_spec.rb
113
+ - spec/lib/sprite_spec.rb
114
+ - spec/lib/stage_spec.rb
115
+ - spec/spec_helper.rb
116
+ has_rdoc: true
117
+ homepage: https://github.com/kapoq/nyan_formatter
118
+ licenses: []
119
+ post_install_message:
120
+ rdoc_options: []
121
+ require_paths:
122
+ - lib
123
+ required_ruby_version: !ruby/object:Gem::Requirement
124
+ none: false
125
+ requirements:
126
+ - - ! '>='
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ required_rubygems_version: !ruby/object:Gem::Requirement
130
+ none: false
131
+ requirements:
132
+ - - ! '>='
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ requirements: []
136
+ rubyforge_project:
137
+ rubygems_version: 1.6.2
138
+ signing_key:
139
+ specification_version: 3
140
+ summary: Nyan Cat flies across your terminal while your RSpec specs run!
141
+ test_files: []