Class: Brut::TUI::Script
- Inherits:
-
Object
- Object
- Brut::TUI::Script
- Defined in:
- lib/brut/tui/script.rb
Overview
A TUI script is a set of steps that are executed in order. Steps can be grouped int phases, and each step can either shell out to an external command or execute Ruby code.
You are intended to subclass this class and implement #execute, which can use
the various methods described here to describe the script. In the context of a
Brut CLI, your subclass would be used inside the CLI::Command#execute method, where
it would call #run! (not #execute).
Inside #execute you should call #phase for each logical phase/grouping of steps. There must be at least
one phase. Inside each phase you should call #step one or more times. When a phase is actually executed,
it's contents are executed, so anything inside the block will be called. Intermediate variables to allow steps to
communicate will work.
After all phases, call done with a success message.
Defined Under Namespace
Modules: Events Classes: BlockStep, ExecStep, LoggingSubscriber, PutsSubscriber, Step
Class Method Summary collapse
-
.log_filename ⇒ Object
Return the basename of a log file unique to this script.
Instance Method Summary collapse
-
#done(message) ⇒ Object
Message to show if the script completes successful.
-
#error(message) ⇒ Object
Let the user know there was an error.
-
#filename(path) ⇒ Object
Wrap a fully-qualified filename in code markup and trim the path to only show the path relative to the root dir.
-
#initialize(root_dir: nil, ansi: true) ⇒ Script
constructor
Create the script.
-
#notify(message) ⇒ Object
Notify the user of an event.
-
#phase(name, &block) ⇒ Object
Create a new phase for the script.
-
#run! ⇒ Object
Entry point for a script.
-
#step(description, exec: nil) { ... } ⇒ Object
A step to run inside a phase.
-
#success(message) ⇒ Object
Let the user know something succeeded.
-
#warning(message) ⇒ Object
Warn the user of an event.
Constructor Details
#initialize(root_dir: nil, ansi: true) ⇒ Script
Create the script. By default, two subscribers are set up: LoggingSubscriber
and PutsSubscriber. The logging subscriber will output a detailed
log into logs/ using the file named by log_filename. The PutsSubscriber will
output ANSI-Fancy messages as the script proceeds.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/brut/tui/script.rb', line 84 def initialize(root_dir: nil, ansi: true) @root_dir = root_dir ? Pathname(root_dir). : nil logs_dir = if @root_dir @root_dir / "logs" else Pathame(".") / "logs" end FileUtils.mkdir_p(logs_dir) @event_loop = Brut::TUI::EventLoop.new logging_subscriber = LoggingSubscriber.new($0, logfile: logs_dir / "#{self.class.log_filename}.log") terminal = Brut::TUI::Terminal.new theme = if ansi Brut::TUI::TerminalTheme.based_on_background(terminal) else Brut::TUI::Themes::None.new(terminal) end puts_subscriber = Brut::TUI::Script::PutsSubscriber.new($0, terminal:, theme:) @event_loop.subscribe(Brut::TUI::Events::EventLoopStarted,self) @event_loop.subscribe_to_all(logging_subscriber) @event_loop.subscribe_to_all(puts_subscriber) end |
Class Method Details
.log_filename ⇒ Object
Return the basename of a log file unique to this script. This will use the subclass name to come up with a reasonable name, however your class can override this.
71 72 73 74 |
# File 'lib/brut/tui/script.rb', line 71 def self.log_filename name = self.name.gsub(/Script$/,"").gsub(/::$/,"").split("::").last name.gsub(/([a-z])([A-Z])/, '\1_\2').downcase end |
Instance Method Details
#done(message) ⇒ Object
Message to show if the script completes successful. Should only be called once and not inside a phase or step.
190 191 192 |
# File 'lib/brut/tui/script.rb', line 190 def done() @done_message = end |
#error(message) ⇒ Object
Let the user know there was an error. Note that this will not stop the script. Raise an exception to do that.
198 199 200 |
# File 'lib/brut/tui/script.rb', line 198 def error() @event_loop << Events::Message.new(message:, type: :error) end |
#filename(path) ⇒ Object
Wrap a fully-qualified filename in code markup and trim the path to only show the path relative to the root dir. This is much friendlier than showing a long expanded path.
207 208 209 210 |
# File 'lib/brut/tui/script.rb', line 207 def filename(path) path = Pathname(path). "`" + (@root_dir ? path.relative_path_from(@root_dir) : path).to_s + "`" end |
#notify(message) ⇒ Object
Notify the user of an event
168 169 170 |
# File 'lib/brut/tui/script.rb', line 168 def notify() @event_loop << Events::Message.new(message:, type: :notification) end |
#phase(name, &block) ⇒ Object
Create a new phase for the script. A phase is basically a named group of steps. The block is not executed immediately, so you may not pass data from one phase to another.
145 146 147 |
# File 'lib/brut/tui/script.rb', line 145 def phase(name, &block) @phases << [ name, block ] end |
#run! ⇒ Object
Entry point for a script. This method starts the event loop.
131 132 133 134 135 136 137 |
# File 'lib/brut/tui/script.rb', line 131 def run! if !self.methods.include?(:execute) raise "You must implement the execute method in your Brut::TUI::Script subclass" end @event_loop.run 0 end |
#step(description, exec: nil) { ... } ⇒ Object
A step to run inside a phase. Steps within phases are executed immediately once the phase has started, so they can pass data to one anther.
156 157 158 159 160 161 162 163 |
# File 'lib/brut/tui/script.rb', line 156 def step(description, exec: nil, &block) step = if exec.nil? BlockStep.new(@event_loop, description, &block) else ExecStep.new(@event_loop, description, command: exec) end step.run! end |