Module: Kino::CLI

Defined in:
lib/kino/cli.rb

Overview

The kino executable (CLI.start) plus startup presentation shared with Server.run: the banner, ANSI styling, and the exit credit. Nothing here is part of the serving API. (The native layer has a twin of paint in style.rs for the few places Rust writes to the terminal.)

This file deliberately loads no native code: require "kino" happens inside the actions that need it, so --help and --version stay instant.

Constant Summary collapse

MOTD =

The plain banner art: "Kino" in TheDraw's Mindbenders font; motd adds the original three-tone shading.

<<~BANNER
  ggg    .o
  $$$_,o$$P aaa $$$eea,.   .,aaa,.
  %$$`4eP'  $$$ $$$``$$$% $$$```$$$
  $$$--`$$o ggg $$$---$$$ $$$---$$$
  $$$ ░ $$$ $$$ $$$ ░ $$$ $$$ ░ $$$
  $$$---$$$ $$$ $$$---$$$ $$$---$$$
  $$$   $$$ $$' $$$   $$$ ^$$aaaS$'
BANNER

Class Method Summary collapse

Class Method Details

.action!(server) ⇒ void

This method returns an undefined value.

Parameters:



121
122
123
124
125
126
# File 'lib/kino/cli.rb', line 121

def action!(server)
  puts dim("- mode:      #{server.mode}")
  puts dim("- listening: http#{"s" if server.tls?}://#{server.bind}:#{server.port}")
  puts dim("- Ctrl-C to drain and stop")
  puts "\n#{bold("Action!")}\n\n"
end

.bold(text, io: $stdout) ⇒ String

Bold styling for headings and the Action!/Fin. bookends.

Returns:

  • (String)


72
73
74
# File 'lib/kino/cli.rb', line 72

def bold(text, io: $stdout)
  paint("1", text, io: io)
end

.color?(io = $stdout) ⇒ Boolean

True when output to io may use ANSI styling.

Parameters:

  • io (IO) (defaults to: $stdout)

Returns:

  • (Boolean)


49
50
51
# File 'lib/kino/cli.rb', line 49

def color?(io = $stdout)
  io.tty? && ENV["NO_COLOR"].nil? && ENV["TERM"] != "dumb"
end

.dim(text, io: $stdout) ⇒ String

Startup-output styling, same gray family as the banner.

Returns:

  • (String)


66
67
68
# File 'lib/kino/cli.rb', line 66

def dim(text, io: $stdout)
  paint("38;5;243", text, io: io)
end

.fin_at_exitvoid

This method returns an undefined value.

Roll credits when the process ends: normal exit or crash (at_exit also runs after an uncaught exception; only a force-exit skips it).



131
132
133
134
135
136
# File 'lib/kino/cli.rb', line 131

def fin_at_exit
  return if @fin_registered

  @fin_registered = true
  at_exit { $stdout.puts bold("\nFin.\n") }
end

.motd(color: color?) ) ⇒ String

The banner with its three-tone shading applied per character.

Parameters:

  • color (Boolean) (defaults to: color?) )

Returns:

  • (String)


85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/kino/cli.rb', line 85

def motd(color: color?)
  return MOTD unless color

  MOTD.lines.zip(MOTD_TONES.lines).map do |art, tones|
    current = nil
    line = art.chomp.each_char.with_index.map { |char, i|
      sgr = TONE_SGR[tones.to_s[i]]
      if char != " " && sgr && sgr != current
        current = sgr
        "\e[#{sgr}m#{char}"
      else
        char
      end
    }.join
    "#{line}\e[0m\n"
  end.join
end

.opening_creditsvoid

This method returns an undefined value.

The two banner halves around Server#start: credits before, the ready block plus a bold "Action!" after, once mode and port are known. Server.run is the one caller; the kino CLI funnels into it.



114
115
116
117
# File 'lib/kino/cli.rb', line 114

def opening_credits
  puts motd
  puts dim("\nKino #{VERSION} presents:")
end

.paint(code, text, io: $stdout) ⇒ String

Wrap text in an SGR code ("1" bold, "31" red, "38;5;N" 256-color), resetting at the end; plain when io is not a color terminal.

Parameters:

  • code (String)

    an SGR code

  • text (String)
  • io (IO) (defaults to: $stdout)

    the stream the text is destined for (gates coloring)

Returns:

  • (String)


60
61
62
# File 'lib/kino/cli.rb', line 60

def paint(code, text, io: $stdout)
  color?(io) ? "\e[#{code}m#{text}\e[0m" : text
end

.red(text, io: $stderr) ⇒ String

Errors are red (gated on stderr unless another io is given).

Returns:

  • (String)


78
79
80
# File 'lib/kino/cli.rb', line 78

def red(text, io: $stderr)
  paint("91", text, io: io)
end

.start(argv) ⇒ Integer

The kino executable: parse flags, then init/check/serve. Returns the process exit status (exe/kino passes it to Kernel#exit), except for -v and -h, which print and exit in place per optparse convention.

Parameters:

  • argv (Array<String>)

    command-line arguments (consumed)

Returns:

  • (Integer)

    process exit status



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/kino/cli.rb', line 144

def start(argv)
  options = {overrides: {}}
  parser = option_parser(options)
  parser.parse!(argv)

  return write_sample(options[:init_path]) if options[:init_path]

  config = resolve_config(options)

  # Precedence for the rackup file: positional arg > `rackup` in config > config.ru
  rackup_file = argv.first || config[:rackup] || "config.ru"
  unless File.exist?(rackup_file)
    warn red("Kino: #{rackup_file} not found")
    puts
    print_help(parser)
    return 1
  end

  ENV["RACK_ENV"] ||= config[:environment] if config[:environment]

  app = Rack::Builder.parse_file(rackup_file)
  app = app.first if app.is_a?(Array) # rack < 3 compat

  return Check.print_report(app) ? 0 : 1 if options[:check]

  serve(app, config)
  0
end

.stats_line(stats) ⇒ String

One-line stats dump (the SIGUSR1 handler's output).

Parameters:

Returns:

  • (String)


106
107
108
# File 'lib/kino/cli.rb', line 106

def stats_line(stats)
  dim("Kino stats: #{stats.map { |k, v| "#{k}=#{v.inspect}" }.join(" ")}")
end