nyancat 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/bin/nyancat +37 -1
  2. data/lib/nyancat.rb +109 -40
  3. metadata +5 -5
@@ -36,6 +36,8 @@ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
36
36
  require 'nyancat'
37
37
  require 'optparse'
38
38
 
39
+ port = 23
40
+ telnet = false
39
41
  options = {}
40
42
  OptionParser.new do |opts|
41
43
  opts.banner = "Usage: nyancat [options]"
@@ -46,6 +48,40 @@ OptionParser.new do |opts|
46
48
  opts.on("-f", "--flavour FLAVOUR", "Available flavours: #{NyanCat.flavours.join(', ')}") do |f|
47
49
  options[:flavour] = f
48
50
  end
51
+ opts.on("-n", "--notime", "Don't show the time nyaned") do |n|
52
+ options[:hide_time] = n
53
+ end
54
+ opts.on("-l", "--listen [PORT]", "Run telnet server on PORT (default 21)") do |p|
55
+ telnet = true
56
+ port = p || 23
57
+ end
58
+ opts.on("-t", "--timeout SECONDS", "Timeout after SECONDS") do |t|
59
+ options[:timeout] = t.to_i
60
+ end
49
61
  end.parse!
50
62
 
51
- NyanCat.nyancat(options)
63
+ if telnet
64
+ # Start a new server listening on specified port
65
+ server = NyanCat::NyanServer.new(port, "::", options)
66
+ server.audit = true
67
+ server.start
68
+ server.join
69
+ else
70
+ stdout = IO.new STDOUT.fileno
71
+
72
+ # Get TTY size
73
+ options[:width], options[:height] = `stty size`.split.map { |x| x.to_i }.reverse
74
+
75
+ begin
76
+ n = NyanCat::NyanCat.new(stdout, options)
77
+ n.run
78
+ rescue SignalException => e
79
+ # Do nothing, exit gracefully
80
+ rescue Exception => e
81
+ puts "Oops, something went wrong..."
82
+ raise e
83
+ end
84
+ end
85
+
86
+
87
+
@@ -31,6 +31,8 @@
31
31
  # WITH THE SOFTWARE.
32
32
 
33
33
  require 'yaml'
34
+ require 'gserver'
35
+ require 'timeout'
34
36
 
35
37
  module NyanCat
36
38
  OUTPUT_CHAR = " "
@@ -39,58 +41,125 @@ module NyanCat
39
41
  return Dir.entries(File.expand_path("../nyancat/", __FILE__)).select { |entry| !(entry =='.' || entry == '..') }
40
42
  end
41
43
 
42
- def self.nyancat(options = {})
43
- flavour = options[:flavour] || 'original'
44
- mute = options[:mute] || false
44
+ class NyanCat
45
+ def initialize(io, options)
46
+ @running = false
47
+ @io = io
48
+ @term_width = options[:width] || 80
49
+ @term_height = options[:height] || 24
50
+ @mute = options[:mute] || false
51
+ @hide_time = options[:hide_time] || false
45
52
 
46
- frames = YAML.load_file(File.expand_path("../nyancat/#{flavour}/frames.yml", __FILE__))
47
- palette = YAML.load_file(File.expand_path("../nyancat/#{flavour}/palette.yml", __FILE__))
48
- audio = File.expand_path("../nyancat/#{flavour}/audio.mp3", __FILE__)
53
+ flavour = options[:flavour] || 'original'
54
+ frames = YAML.load_file(File.expand_path("../nyancat/#{flavour}/frames.yml", __FILE__))
55
+ palette = YAML.load_file(File.expand_path("../nyancat/#{flavour}/palette.yml", __FILE__))
49
56
 
50
- # Get TTY size
51
- term_width, term_height = `stty size`.split.map { |x| x.to_i }.reverse
57
+ @audio = File.expand_path("../nyancat/#{flavour}/audio.mp3", __FILE__)
52
58
 
53
- # Calculate the width in terms of the output char
54
- term_width = term_width / OUTPUT_CHAR.length
59
+ # Calculate the width in terms of the output char
60
+ term_width = @term_width / OUTPUT_CHAR.length
61
+ term_height = @term_height
55
62
 
56
- min_row = 0
57
- max_row = frames[0].length
63
+ min_row = 0
64
+ max_row = frames[0].length
58
65
 
59
- min_col = 0
60
- max_col = frames[0][0].length
66
+ min_col = 0
67
+ max_col = frames[0][0].length
61
68
 
62
- min_row = (max_row - term_height) / 2 if max_row > term_height
63
- max_row = min_row + term_height if max_row > term_height
69
+ min_row = (max_row - term_height) / 2 if max_row > term_height
70
+ max_row = min_row + term_height if max_row > term_height
64
71
 
65
- min_col = (max_col - term_width) / 2 if max_col > term_width
66
- max_col = min_col + term_width if max_col > term_width
72
+ min_col = (max_col - term_width) / 2 if max_col > term_width
73
+ max_col = min_col + term_width if max_col > term_width
67
74
 
68
- frames = frames.map do |frame|
69
- frame[min_row...max_row].map do |line|
70
- line.chars.to_a[min_col...max_col].map do |c|
71
- "\033[48;5;%dm%s" % [palette[c], OUTPUT_CHAR]
72
- end.join + "\033[m\n"
73
- end.join + "\033[H"
75
+ # Calculate the final animation width
76
+ @anim_width = (max_col - min_col) * OUTPUT_CHAR.length
77
+
78
+ # Precompute frames
79
+ @frames = frames.map do |frame|
80
+ frame[min_row...max_row].map do |line|
81
+ line.chars.to_a[min_col...max_col].map do |c|
82
+ "\033[48;5;%dm%s" % [palette[c], OUTPUT_CHAR]
83
+ end.join + "\033[m\n"
84
+ end
85
+ end
74
86
  end
75
87
 
76
- audio_thread = Thread.new { IO.popen("mpg123 -loop 0 -q #{audio} > /dev/null 2>&1") } unless mute
77
-
78
- start_time = Time.now
79
- printf("\033[H\033[2J\033[?25l")
80
- begin
81
- loop do
82
- frames.each do |frame|
83
- print frame
84
- sleep(0.09)
88
+ def run()
89
+ @running = true
90
+
91
+ begin
92
+ # Initialise term
93
+ @io.printf("\033[H\033[2J\033[?25l")
94
+
95
+ # Get start time
96
+ start_time = Time.now()
97
+
98
+ # Play audio
99
+ audio_t = Thread.new { IO.popen("mpg123 -loop 0 -q #{@audio} > /dev/null 2>&1") } unless @mute || nil
100
+
101
+ while @running
102
+ @frames.each do |frame|
103
+ # Print the next frame
104
+ @io.puts frame
105
+
106
+ # Print the time so far
107
+ unless @hide_time
108
+ time = "You have nyaned for %0.0f seconds!" % [Time.now() - start_time]
109
+ time = time.center(@anim_width)
110
+ @io.printf("\033[1;37;17m%s", time)
111
+ end
112
+
113
+ # Reset the frame and sleep
114
+ @io.printf("\033[H")
115
+ sleep(0.09)
116
+ end
85
117
  end
118
+
119
+ ensure
120
+ # Ensure the audio thread is killed, if it exists
121
+ audio_t.kill unless audio_t.nil?
122
+ stop
123
+ reset
124
+ end
125
+ end
126
+
127
+ def stop()
128
+ @running = false
129
+ end
130
+
131
+ def reset()
132
+ begin
133
+ @io.puts("\033[0m\033c")
134
+ rescue Errno::EPIPE => e
135
+ # We failed to reset the TERM, IO stream is gone
86
136
  end
87
- rescue SignalException => e
88
- printf("\033c\033c")
89
- printf("YOU NYANED FOR %4.2f SECONDS\n", Time.now - start_time)
90
- rescue Exception => e
91
- printf("\033c")
92
- puts "Oops, something went wrong..."
93
- raise e
94
137
  end
95
138
  end
139
+
140
+ class NyanServer < GServer
141
+ def initialize(port, address, options = {})
142
+ @options = options
143
+ @options[:mute] = true
144
+ @timeout = @options[:timeout]
145
+ super(port, address)
146
+ end
147
+
148
+ def serve(io)
149
+ n = NyanCat.new(io, @options)
150
+ begin
151
+ # run the animation thread
152
+ t = Thread.new(n) { |nyan| nyan.run() }
153
+
154
+ # block until any input is received or timeout is reached, then die
155
+ Timeout::timeout(@timeout) { io.readline() }
156
+ rescue Exception => e
157
+ log("Client error: #{e}")
158
+ ensure
159
+ n.stop
160
+ t.join
161
+ end
162
+ end
163
+ end
164
+
96
165
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nyancat
3
3
  version: !ruby/object:Gem::Version
4
+ version: 0.2.0
4
5
  prerelease:
5
- version: 0.1.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Ben Arblaster
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-01 00:00:00.000000000 Z
12
+ date: 2013-02-01 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: A Ruby port of Kevin Lange's nyancat
15
15
  email: ben@andatche.com
@@ -30,20 +30,20 @@ rdoc_options: []
30
30
  require_paths:
31
31
  - lib
32
32
  required_ruby_version: !ruby/object:Gem::Requirement
33
+ none: false
33
34
  requirements:
34
35
  - - ! '>='
35
36
  - !ruby/object:Gem::Version
36
37
  version: '0'
37
- none: false
38
38
  required_rubygems_version: !ruby/object:Gem::Requirement
39
+ none: false
39
40
  requirements:
40
41
  - - ! '>='
41
42
  - !ruby/object:Gem::Version
42
43
  version: '0'
43
- none: false
44
44
  requirements: []
45
45
  rubyforge_project:
46
- rubygems_version: 1.8.23
46
+ rubygems_version: 1.8.25
47
47
  signing_key:
48
48
  specification_version: 3
49
49
  summary: nyancat on your terminal