Class: VER::View::Console

Inherits:
Object
  • Object
show all
Defined in:
lib/ver/view/console.rb

Defined Under Namespace

Classes: Process, Stderr

Instance Method Summary collapse

Constructor Details

#initialize(parent, *cmd) ⇒ Console

Returns a new instance of Console.



30
31
32
33
34
35
# File 'lib/ver/view/console.rb', line 30

def initialize(parent, *cmd)
  @parent = parent
  setup_widgets
  setup_events
  setup_terminal(*cmd)
end

Instance Method Details

#closedObject



72
73
74
75
76
77
78
79
# File 'lib/ver/view/console.rb', line 72

def closed
  @entry.bind('<Return>'){}
  @entry.bind('<Key>'){ Tk.callback_break }
  @entry.bind('<Escape>'){ destroy }
  @entry.value = 'Session ended. Press Escape to close console'
rescue => ex
  VER.error(ex)
end

#destroyObject



81
82
83
84
85
# File 'lib/ver/view/console.rb', line 81

def destroy
  @text.destroy
  @entry.destroy
  @parent.focus
end

#on_stderr(string) ⇒ Object



161
162
163
# File 'lib/ver/view/console.rb', line 161

def on_stderr(string)
  output "e> #{string}", :stderr
end

#on_stdin(string) ⇒ Object



153
154
155
# File 'lib/ver/view/console.rb', line 153

def on_stdin(string)
  output "i> #{string}\n", :stdin
end

#on_stdout(string) ⇒ Object



157
158
159
# File 'lib/ver/view/console.rb', line 157

def on_stdout(string)
  output "#{string}", :stdout
end

#output(string, tag) ⇒ Object



165
166
167
168
# File 'lib/ver/view/console.rb', line 165

def output(string, tag)
  @text.insert(:end, string, tag)
  @text.see(:end)
end

#popen3(cmd, callback) {|popen_stdin| ... } ⇒ Object

the callback should have #on_stdout and #on_stderr The method yields the stdin and you can use #send_data on it. This seems to have the side-effect of messing with the original $stderr, maybe there are other solutions.

Yields:

  • (popen_stdin)


132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/ver/view/console.rb', line 132

def popen3(cmd, callback)
  old_stderr = $stderr.dup
  rd, wr = IO::pipe
  $stderr.reopen(wr)

  popen_stdin = EM.popen(cmd, Process)
  popen_stdin.callback = callback

  popen_stderr = EM.attach(rd, Stderr, rd)
  popen_stderr.callback = callback

  yield(popen_stdin) if block_given?

  $stderr.reopen old_stderr
end

#send_data(string) ⇒ Object



148
149
150
151
# File 'lib/ver/view/console.rb', line 148

def send_data(string)
  @stdin.send_data("#{string}\n")
  on_stdin(string)
end

#setup_eventsObject



63
64
65
66
67
68
69
70
# File 'lib/ver/view/console.rb', line 63

def setup_events
  @entry.bind('<Control-q>'){ Tk.exit }
  # @entry.bind('Escape'){ closed }
  @entry.bind('<Return>'){
    send_data @entry.value
    @entry.clear
  }
end

#setup_terminal(*cmd) ⇒ Object



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/ver/view/console.rb', line 105

def setup_terminal(*cmd)
  if cmd.empty?
    @buffer, opts = shell_config
  else
    @buffer = []
    opts = cmd
  end

  # FIXME: this should have proper shell escapes
  popen3(opts.join(' '), self) do |stdin|
    begin
      @entry.focus
      @stdin = stdin

      while line = @buffer.shift
        send_data(line)
      end
    rescue => ex
      VER.error(ex)
    end
  end
end

#setup_widgetsObject



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/ver/view/console.rb', line 37

def setup_widgets
  font = VER.options[:font]
  tab_width = font.measure('0') * 2

  @text = Tk::Text.new(
    @parent,
    borderwidth: 0,
    exportselection: true,
    font: font,
    insertofftime: 0,
    setgrid: true,
    tabs: tab_width,
    tabstyle: :wordprocessor,
    background: 'black',
    foreground: 'white',
    wrap: :word
  )
  @text.tag_configure :stdin,  foreground: 'green', background: 'black'
  @text.tag_configure :stdout, foreground: 'white', background: 'black'
  @text.tag_configure :stderr, foreground: 'red',   background: 'black'

  @entry = Tk::Tile::Entry.new(@parent)
  @entry.pack fill: :x, side: :bottom
  @text.pack fill: :both, side: :bottom, after: @entry, expand: true
end

#shell_configObject



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/ver/view/console.rb', line 87

def shell_config
  buffer = []

  shell = ENV['SHELL'] || 'sh'
  opts = [shell]

  case shell
  when /zsh/
    opts << '-s'
    buffer << 'echo $ZSH $ZSH_VERSION'
  when /bash/
    opts << '-s'
    buffer << 'echo $BASH $BASH_VERSION'
  end

  return buffer, opts
end