Class: Tap::Tasks::Prompt
- Includes:
- Utils
- Defined in:
- lib/tap/tasks/prompt.rb
Overview
:startdoc::task open a prompt
Prompt reads signals from the input until a signal that returns the app is reached (ex run/stop) or the source io is closed.
% tap prompt
/set 0 load
/set 1 dump
/build join 0 1
/enq 0 'goodnight moon'
/run
goodnight moon
Prompts can be registered to a control signal (ex INT) so that that a running app may be interrupted, interrogated, or modified. This infinite loop can be stopped using ctl-C and a prompt.
% tap dump '.' - join 0 0 -q - prompt --on INT
.
.
.
(ctl-C)
/stop
Instance Attribute Summary
Attributes inherited from Tap::Task
Attributes inherited from App::Api
Instance Method Summary collapse
- #complete?(io, result) ⇒ Boolean
-
#initialize(*args) ⇒ Prompt
constructor
A new instance of Prompt.
- #load(io) ⇒ Object
- #process(io = $stdin) ⇒ Object
- #readline(io) ⇒ Object
- #signal(sig) ⇒ Object
-
#trap(sig) ⇒ Object
Traps interrupt the normal flow of the program and so I assume thread safety is an issue (ex if the INT occurs during an enque and a signal specifies another enque).
Methods included from Utils
set_env, sh, sh_escape, shellsplit, with_env
Methods inherited from Stream
Methods inherited from Load
Methods inherited from Tap::Task
#associations, #call, #enq, #exe, #log, #on_complete, parser
Methods inherited from App::Api
#associations, build, help, inherited, #inspect, parse, parse!, parser, #to_spec
Methods included from Signals
Methods included from Signals::ModuleMethods
Constructor Details
#initialize(*args) ⇒ Prompt
Returns a new instance of Prompt.
38 39 40 41 |
# File 'lib/tap/tasks/prompt.rb', line 38 def initialize(*args) super trap(on) if on end |
Instance Method Details
#complete?(io, result) ⇒ Boolean
123 124 125 |
# File 'lib/tap/tasks/prompt.rb', line 123 def complete?(io, result) result == app end |
#load(io) ⇒ Object
97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/tap/tasks/prompt.rb', line 97 def load(io) line = readline(io) return nil if line.empty? begin sig, *args = shellsplit(line) app.call('sig' => sig, 'args' => args) rescue $! end end |
#process(io = $stdin) ⇒ Object
83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/tap/tasks/prompt.rb', line 83 def process(io=$stdin) app.set(variable, self) if variable result = super(io) unless file || result.nil? || result == app open_io(terminal) do |terminal| terminal.puts result end end app.set(variable, nil) if variable result end |
#readline(io) ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/tap/tasks/prompt.rb', line 109 def readline(io) if io == $stdin && terminal == $stdout return Readline.readline(prompt, true) end if prompt && !file open_io(terminal) do |terminal| terminal.print prompt end end io.eof? ? '' : io.readline.strip! end |
#signal(sig) ⇒ Object
75 76 77 78 79 80 81 |
# File 'lib/tap/tasks/prompt.rb', line 75 def signal(sig) lambda do |spec| app.build('class' => sig, 'spec' => spec) do |obj, args| obj.call(args) end end end |
#trap(sig) ⇒ Object
Traps interrupt the normal flow of the program and so I assume thread safety is an issue (ex if the INT occurs during an enque and a signal specifies another enque). A safer way to go is to enque the prompt… when the prompt is executed the app won’t be be doing anything else so thread safety shouldn’t be an issue.
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 |
# File 'lib/tap/tasks/prompt.rb', line 48 def trap(sig) ::Signal.trap(sig) do puts puts "Interrupt! Signals from an interruption are not thread-safe." call_prompt = true 3.times do print "Wait for thread-safe break? (y/n): " case gets.strip when /^y(es)?$/i puts "waiting for break..." app.pq(self, []) call_prompt = false break when /^no?$/i break end end if call_prompt call([]) end end end |