Module: Expectr::Lambda

Includes:
Interface
Defined in:
lib/expectr/lambda.rb,
lib/expectr/errstr.rb

Overview

Public: The Expectr::Lambda Module defines the interface for interacting with Proc objects in a manner which is similar to interacting with processes.

Defined Under Namespace

Modules: Errstr

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Interface

#prepare_interact_interface

Class Method Details

.spawn(reader, writer, args = {}) ⇒ Object

Public: Present a streamlined interface to create a new Expectr instance.

reader - Lambda which is meant to be interacted with as if it were

analogous to STDIN for a child process.

writer - Lambda which is meant to be interacted with as if it were

analogous to STDOUT for a child process.

args - A Hash used to specify options for the new object, per

Expectr#initialize.

Returns a new Expectr object



40
41
42
43
44
45
# File 'lib/expectr/lambda.rb', line 40

def self.spawn(reader, writer, args = {})
  args[:interface] = :lambda
  args[:reader] = reader
  args[:writer] = writer
  Expectr.new(args)
end

Instance Method Details

#init_interface(args) ⇒ Object

Public: Initialize the Expectr Lambda interface.

args - Hash containing Proc objects to act as reader and writer:

reader - Lambda which is meant to be interacted with as if it were
         analogous to STDIN for a child process.
writer - Lambda which is meant to be interacted with as if it were
         analogous to STDOUT for a child process.

Raises TypeError if arguments aren’t of type Proc.



20
21
22
23
24
25
26
27
28
# File 'lib/expectr/lambda.rb', line 20

def init_interface(args)
  unless args[:reader].kind_of?(Proc) && args[:writer].kind_of?(Proc)
    raise(TypeError, Errstr::PROC_EXPECTED)
  end

  @pid = -1
  @reader = args[:reader]
  @writer = args[:writer]
end

#interact_threadObject

Public: Create a Thread containing the loop which is responsible for handling input from the user in interact mode.

Returns a Thread containing the running loop.



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

def interact_thread
  Thread.new do
    env = prepare_interact_environment
    input = ''

    while @interact
      if select([$stdin], nil, nil, 1)
        c = $stdin.getc.chr
        send c unless c.nil?
      end
    end

    restore_environment(env)
  end
end

#prepare_interact_environmentObject

Public: Prepare the operating environment for interact mode, set the interact flag to true.

Returns a Hash containing old signal handlers and tty parameters.



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/expectr/lambda.rb', line 60

def prepare_interact_environment
  env = {sig: {}}

  # Save old tty settings and set up the new environment
  env[:tty] = `stty -g`
  `stty -icanon min 1 time 0 -echo`

  # SIGINT should be sent to the child as \C-c
  env[:sig]['INT'] = trap 'INT' do
    send "\C-c"
  end

  # SIGTSTP should be sent to the process as \C-z
  env[:sig]['TSTP'] = trap 'TSTP' do
    send "\C-z"
  end

  @interact = true
  env
end

#send(args) ⇒ Object

Public: Send input to the reader Proc.

args - Arguments to pass to the reader interface.

Returns nothing.



52
53
54
# File 'lib/expectr/lambda.rb', line 52

def send(args)
  @reader.call(*args)
end