Module: Lol

Defined in:
lib/lolcat/cat.rb,
lib/lolcat/lol.rb

Constant Summary collapse

ANSI_ESCAPE =
/((?:\e(?:[ -\/]+.|[\]PX^_][^\a\e]*|\[[0-?]*.|.))*)(.?)/m
INCOMPLETE_ESCAPE =
/\e(?:[ -\/]*|[\]PX^_][^\a\e]*|\[[0-?]*)$/

Class Method Summary collapse

Class Method Details

.cat(fd, opts = {}) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/lolcat/lol.rb', line 43

def self.cat(fd, opts={})
  @os = opts[:os]
  print "\e[?25l" if opts[:animate]
  while true do
    buf = ''
    begin
      begin
        buf += fd.sysread(4096)
        invalid_encoding = !buf.dup.force_encoding(fd.external_encoding).valid_encoding?
      end while invalid_encoding or buf.match(INCOMPLETE_ESCAPE)
    rescue EOFError
      break
    end
    buf.force_encoding(fd.external_encoding)
    buf.lines.each do |line|
      @os += 1
      println(line, opts)
    end
  end
  ensure
  if STDOUT.tty? then
      print "\e[m\e[?25h\e[?1;5;2004l"
      # system("stty sane -istrip <&1");
  end
end

.cat!Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/lolcat/cat.rb', line 33

def self.cat!
  p = Optimist::Parser.new do
    version "lolcat #{Lolcat::VERSION} (c)2011 [email protected]"
    banner <<HEADER

Usage: lolcat [OPTION]... [FILE]...

Concatenate FILE(s), or standard input, to standard output.
With no FILE, or when FILE is -, read standard input.

HEADER
    banner ''
    opt :spread, "Rainbow spread", :short => 'p', :default => 3.0
    opt :freq, "Rainbow frequency", :short => 'F', :default => 0.1
    opt :seed, "Rainbow seed, 0 = random", :short => 'S', :default => 0
    opt :animate, "Enable psychedelics", :short => 'a', :default => false
    opt :duration, "Animation duration", :short => 'd', :default => 12
    opt :speed, "Animation speed", :short => 's', :default => 20.0
    opt :invert, "Invert fg and bg", :short => 'i', :default => false
    opt :truecolor, "24-bit (truecolor)", :short => 't', :default => false
    opt :force, "Force color even when stdout is not a tty", :short => 'f', :default => false
    opt :version,  "Print version and exit", :short => 'v'
    opt :help,  "Show this message", :short => 'h'
    banner <<FOOTER

Examples:
lolcat f - g      Output f's contents, then stdin, then g's contents.
lolcat            Copy standard input to standard output.
fortune | lolcat  Display a rainbow cookie.

Report lolcat bugs to <https://github.com/busyloop/lolcat/issues>
lolcat home page: <https://github.com/busyloop/lolcat/>
Report lolcat translation bugs to <http://speaklolcat.com/>

FOOTER
  end

  opts = Optimist::with_standard_exception_handling p do
    begin
      o = p.parse ARGV
    rescue Optimist::HelpNeeded
      buf = StringIO.new
      p.educate buf
      buf.rewind
      opts = {
        :animate => false,
        :duration => 12,
        :os => rand * 8192,
        :speed => 20,
        :spread => 8.0,
        :freq => 0.3
      }
      Lol.cat buf, opts
      puts
      buf.close
      exit 1
    end
    o
  end

  p.die :spread, "must be >= 0.1" if opts[:spread] < 0.1
  p.die :duration, "must be >= 0.1" if opts[:duration] < 0.1
  p.die :speed, "must be >= 0.1" if opts[:speed] < 0.1

  opts[:os] = opts[:seed]
  opts[:os] = rand(256) if opts[:os] == 0

  begin
    files = ARGV.empty? ? [:stdin] : ARGV[0..-1]
    files.each do |file|
      fd = $stdin if file == '-' or file == :stdin
      begin
        fd = File.open(file, "r") unless fd == $stdin

        if $stdout.tty? or opts[:force]
          Lol.cat fd, opts
        else
          if fd.tty?
            fd.each do |line|
              $stdout.write(line)
            end
          else
            IO.copy_stream(fd, $stdout)
          end
        end
      rescue Errno::ENOENT
        puts "lolcat: #{file}: No such file or directory"
        exit 1
      rescue Errno::EACCES
        puts "lolcat: #{file}: Permission denied"
        exit 1
      rescue Errno::EISDIR
        puts "lolcat: #{file}: Is a directory"
        exit 1
      rescue Errno::EPIPE
        exit 1
      end
    end
  rescue Interrupt
  end
end

.println(str, defaults = {}, opts = {}) ⇒ Object



69
70
71
72
73
74
75
# File 'lib/lolcat/lol.rb', line 69

def self.println(str, defaults={}, opts={})
  opts.merge!(defaults)
  chomped = str.sub!(/\n$/, "")
  str.gsub! "\t", "        "
  opts[:animate] ? println_ani(str, opts, chomped) : println_plain(str, opts, chomped)
  puts if chomped
end

.rainbow(freq, i) ⇒ Object



36
37
38
39
40
41
# File 'lib/lolcat/lol.rb', line 36

def self.rainbow(freq, i)
   red   = Math.sin(freq*i + 0) * 127 + 128
   green = Math.sin(freq*i + 2*Math::PI/3) * 127 + 128
   blue  = Math.sin(freq*i + 4*Math::PI/3) * 127 + 128
   "#%02X%02X%02X" % [ red, green, blue ]
end