Class Tap::Tasks::Prompt
In: lib/tap/tasks/prompt.rb
Parent: Stream

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

Methods

complete?   load   new   process   readline   signal   trap  

Included Modules

Tap::Utils

Configurations

on  [RW]  Register to a SIG (nil)
prompt  [RW]  The prompt sequence (’/’)
terminal  [RW]  The terminal IO ($stdout)
variable  [RW]  Assign to variable in app (’’)

Public Class methods

[Source]

    # File lib/tap/tasks/prompt.rb, line 38
38:       def initialize(*args)
39:         super
40:         trap(on) if on
41:       end

Public Instance methods

[Source]

     # File lib/tap/tasks/prompt.rb, line 123
123:       def complete?(io, result)
124:         result == app
125:       end

[Source]

     # File lib/tap/tasks/prompt.rb, line 97
 97:       def load(io)
 98:         line = readline(io)
 99:         return nil if line.empty?
100:         
101:         begin
102:           sig, *args = shellsplit(line)
103:           app.call('sig' => sig, 'args' => args)
104:         rescue
105:           $!
106:         end
107:       end

[Source]

    # File lib/tap/tasks/prompt.rb, line 83
83:       def process(io=$stdin)
84:         app.set(variable, self) if variable
85:         
86:         result = super(io)
87:         unless file || result.nil? || result == app
88:           open_io(terminal) do |terminal|
89:             terminal.puts result
90:           end
91:         end
92:         
93:         app.set(variable, nil) if variable
94:         result
95:       end

[Source]

     # File lib/tap/tasks/prompt.rb, line 109
109:       def readline(io)
110:         if io == $stdin && terminal == $stdout
111:           return Readline.readline(prompt, true)
112:         end
113:         
114:         if prompt && !file
115:           open_io(terminal) do |terminal|
116:             terminal.print prompt
117:           end
118:         end
119:         
120:         io.eof? ? '' : io.readline.strip!
121:       end

[Source]

    # File lib/tap/tasks/prompt.rb, line 75
75:       def signal(sig)
76:         lambda do |spec|
77:           app.build('class' => sig, 'spec' => spec) do |obj, args|
78:             obj.call(args)
79:           end
80:         end
81:       end

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.

[Source]

    # File lib/tap/tasks/prompt.rb, line 48
48:       def trap(sig)
49:         ::Signal.trap(sig) do
50:           puts
51:           puts "Interrupt! Signals from an interruption are not thread-safe."
52:           
53:           call_prompt = true
54:           3.times do
55:             print "Wait for thread-safe break? (y/n): "
56: 
57:             case gets.strip
58:             when /^y(es)?$/i
59:               puts "waiting for break..."
60:               app.pq(self, [])
61:               call_prompt = false
62:               break
63: 
64:             when /^no?$/i
65:               break
66:             end
67:           end
68: 
69:           if call_prompt
70:             call([])
71:           end
72:         end
73:       end

[Validate]