Module: Unmagic::Browser::Console

Defined in:
lib/unmagic/browser/console.rb,
lib/unmagic/browser/console/banner.rb,
lib/unmagic/browser/console/prompt.rb,
lib/unmagic/browser/console/values.rb,
lib/unmagic/browser/console/helpers.rb,
lib/unmagic/browser/console/graphics.rb,
lib/unmagic/browser/console/renderer.rb,
lib/unmagic/browser/console/terminal.rb

Overview

A browser you can type at.

open "https://example.com"
click "More information"
screenshot

Not required by unmagic/browser — it's for a person at a terminal, not for an app, and it takes over main and IRB's output when it starts. Require it yourself:

require "unmagic/browser/console"
Unmagic::Browser::Console.start

Every result is rendered rather than inspected: source is syntax highlighted, screenshots are drawn in the terminal, elements and sessions get a summary worth reading. Highlighting wants rouge — the console works without it, just in monochrome — and drawing images wants a terminal that speaks the kitty graphics protocol (kitty, Ghostty, WezTerm). Neither is a dependency.

Defined Under Namespace

Modules: Banner, Graphics, Helpers, Prompt, Renderer, Terminal Classes: Code, Document, Image, NothingOpen, Tagged

Constant Summary collapse

ENV_LINE =

One line of a dotenv file: an optional export, a name, an =, a value that may be quoted, and an optional trailing comment.

/\A\s*(?:export\s+)?([A-Z_][A-Z0-9_]*)\s*=\s*(.*?)\s*\z/i

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.sessionUnmagic::Browser::Session?

Returns the session the verbs are driving.

Returns:



52
53
54
# File 'lib/unmagic/browser/console.rb', line 52

def session
  @session
end

Class Method Details

.browserUnmagic::Browser

The browser every verb runs against, built on first use.

Returns:



47
48
49
# File 'lib/unmagic/browser/console.rb', line 47

def browser
  @browser ||= Unmagic::Browser.new(driver: @driver || :local)
end

.load_env(path) ⇒ Array<String>

Read a dotenv file into ENV, if it's there. Values already in the environment win — an export in your shell should beat a checked-in file.

Parameters:

  • path (String)

    the file to read

Returns:

  • (Array<String>)

    the names that were set



105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/unmagic/browser/console.rb', line 105

def load_env(path)
  return [] unless File.exist?(path)

  File.readlines(path).filter_map do |line|
    next if line.strip.empty? || line.strip.start_with?("#")

    name, raw = ENV_LINE.match(line)&.captures
    next unless name && !ENV.key?(name)

    ENV[name] = unquote(raw)
    name
  end
end

.reset(driver = nil) ⇒ void

This method returns an undefined value.

Throw away the browser and any session, so the next verb builds a new one.

Parameters:



58
59
60
61
62
63
64
# File 'lib/unmagic/browser/console.rb', line 58

def reset(driver = nil)
  session&.close
  @session = nil
  @browser&.close
  @browser = nil
  @driver = driver if driver
end

.start(context: TOPLEVEL_BINDING, banner: true, prompt: :plain) ⇒ void

This method returns an undefined value.

Mix the verbs into an object — main, in a console — and start IRB.

Parameters:

  • context (Binding) (defaults to: TOPLEVEL_BINDING)

    whose receiver gets the verbs, and where IRB runs

  • banner (Boolean) (defaults to: true)

    print the banner and the verb list first

  • prompt (Symbol) (defaults to: :plain)

    :plain for browser>, or :page for a prompt that follows the browser around — see Prompt



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
# File 'lib/unmagic/browser/console.rb', line 73

def start(context: TOPLEVEL_BINDING, banner: true, prompt: :plain)
  require "irb"
  require "irb/workspace"

  # Only the one object gets the verbs, rather than every Object in the
  # process — `open` and `select` shadow Kernel's, which is a trade
  # worth making for `main` and nothing else.
  context.receiver.extend(Helpers)
  at_exit { reset rescue nil }

  if banner
    puts(Banner.render)
    puts(Banner.help)
  end

  ARGV.clear
  IRB.setup(nil)
  # After `setup`, never before: it resets IRB.conf, which would throw
  # away a prompt registered ahead of it and leave PROMPT_MODE pointing
  # at nothing.
  configure
  irb = IRB::Irb.new(IRB::WorkSpace.new(context))
  Prompt.install(irb.context) if prompt == :page
  irb.run(IRB.conf)
end