yap-shell 0.7.1 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +9 -24
  3. data/Gemfile +1 -5
  4. data/LICENSE.txt +17 -18
  5. data/README.md +28 -14
  6. data/Rakefile +4 -1
  7. data/bin/yap +1 -3
  8. data/lib/.gitkeep +0 -0
  9. data/yap-shell.gemspec +12 -11
  10. metadata +19 -184
  11. data/.rspec +0 -2
  12. data/.travis.yml +0 -11
  13. data/DESIGN.md +0 -87
  14. data/Gemfile.travis +0 -8
  15. data/Gemfile.travis.lock +0 -104
  16. data/WISHLIST.md +0 -54
  17. data/bin/yap-dev +0 -45
  18. data/lib/tasks/gem.rake +0 -62
  19. data/lib/yap.rb +0 -52
  20. data/lib/yap/addon.rb +0 -24
  21. data/lib/yap/addon/base.rb +0 -52
  22. data/lib/yap/addon/export_as.rb +0 -12
  23. data/lib/yap/addon/loader.rb +0 -84
  24. data/lib/yap/addon/path.rb +0 -56
  25. data/lib/yap/addon/rc_file.rb +0 -21
  26. data/lib/yap/addon/reference.rb +0 -22
  27. data/lib/yap/cli.rb +0 -4
  28. data/lib/yap/cli/commands.rb +0 -6
  29. data/lib/yap/cli/commands/addon.rb +0 -14
  30. data/lib/yap/cli/commands/addon/disable.rb +0 -35
  31. data/lib/yap/cli/commands/addon/enable.rb +0 -35
  32. data/lib/yap/cli/commands/addon/list.rb +0 -37
  33. data/lib/yap/cli/commands/addon/search.rb +0 -99
  34. data/lib/yap/cli/commands/generate.rb +0 -13
  35. data/lib/yap/cli/commands/generate/addon.rb +0 -258
  36. data/lib/yap/cli/commands/generate/addonrb.template +0 -22
  37. data/lib/yap/cli/commands/generate/gemspec.template +0 -25
  38. data/lib/yap/cli/commands/generate/license.template +0 -21
  39. data/lib/yap/cli/commands/generate/rakefile.template +0 -6
  40. data/lib/yap/cli/commands/generate/readme.template +0 -40
  41. data/lib/yap/cli/options.rb +0 -162
  42. data/lib/yap/cli/options/addon.rb +0 -64
  43. data/lib/yap/cli/options/addon/disable.rb +0 -62
  44. data/lib/yap/cli/options/addon/enable.rb +0 -63
  45. data/lib/yap/cli/options/addon/list.rb +0 -65
  46. data/lib/yap/cli/options/addon/search.rb +0 -76
  47. data/lib/yap/cli/options/generate.rb +0 -59
  48. data/lib/yap/cli/options/generate/addon.rb +0 -63
  49. data/lib/yap/configuration.rb +0 -74
  50. data/lib/yap/gem_helper.rb +0 -195
  51. data/lib/yap/gem_tasks.rb +0 -6
  52. data/lib/yap/shell.rb +0 -116
  53. data/lib/yap/shell/aliases.rb +0 -58
  54. data/lib/yap/shell/builtins.rb +0 -18
  55. data/lib/yap/shell/builtins/alias.rb +0 -42
  56. data/lib/yap/shell/builtins/cd.rb +0 -57
  57. data/lib/yap/shell/builtins/env.rb +0 -11
  58. data/lib/yap/shell/commands.rb +0 -163
  59. data/lib/yap/shell/evaluation.rb +0 -439
  60. data/lib/yap/shell/evaluation/shell_expansions.rb +0 -99
  61. data/lib/yap/shell/event_emitter.rb +0 -18
  62. data/lib/yap/shell/execution.rb +0 -16
  63. data/lib/yap/shell/execution/builtin_command_execution.rb +0 -20
  64. data/lib/yap/shell/execution/command_execution.rb +0 -30
  65. data/lib/yap/shell/execution/context.rb +0 -128
  66. data/lib/yap/shell/execution/file_system_command_execution.rb +0 -137
  67. data/lib/yap/shell/execution/result.rb +0 -18
  68. data/lib/yap/shell/execution/ruby_command_execution.rb +0 -80
  69. data/lib/yap/shell/execution/shell_command_execution.rb +0 -30
  70. data/lib/yap/shell/prompt.rb +0 -21
  71. data/lib/yap/shell/repl.rb +0 -237
  72. data/lib/yap/shell/version.rb +0 -5
  73. data/lib/yap/world.rb +0 -286
  74. data/rcfiles/yaprc +0 -390
  75. data/scripts/4 +0 -8
  76. data/scripts/bg-vim +0 -4
  77. data/scripts/fail +0 -3
  78. data/scripts/letters +0 -8
  79. data/scripts/lots-of-output +0 -6
  80. data/scripts/pass +0 -3
  81. data/scripts/simulate-long-running +0 -4
  82. data/scripts/write-to-stderr.rb +0 -3
  83. data/scripts/write-to-stdout.rb +0 -3
  84. data/spec/features/addons/generating_an_addon_spec.rb +0 -55
  85. data/spec/features/addons/using_an_addon_spec.rb +0 -182
  86. data/spec/features/aliases_spec.rb +0 -78
  87. data/spec/features/environment_variables_spec.rb +0 -69
  88. data/spec/features/filesystem_commands_spec.rb +0 -61
  89. data/spec/features/first_time_spec.rb +0 -45
  90. data/spec/features/grouping_spec.rb +0 -81
  91. data/spec/features/line_editing_spec.rb +0 -174
  92. data/spec/features/range_spec.rb +0 -35
  93. data/spec/features/redirection_spec.rb +0 -234
  94. data/spec/features/repetition_spec.rb +0 -118
  95. data/spec/features/shell_expansions_spec.rb +0 -127
  96. data/spec/spec_helper.rb +0 -172
  97. data/spec/support/matchers/have_not_printed.rb +0 -30
  98. data/spec/support/matchers/have_printed.rb +0 -68
  99. data/spec/support/very_soon.rb +0 -9
  100. data/spec/support/yap_spec_dsl.rb +0 -258
  101. data/test.rb +0 -206
  102. data/update-rawline.sh +0 -6
@@ -1,18 +0,0 @@
1
- module Yap::Shell::Execution
2
- class Result
3
- attr_reader :status_code, :directory, :n, :of
4
-
5
- def initialize(status_code:, directory:, n:, of:)
6
- @status_code = status_code
7
- @directory = directory
8
- @n = n
9
- @of = of
10
- end
11
- end
12
-
13
- class SuspendExecution < Result
14
- end
15
-
16
- class ResumeExecution < Result
17
- end
18
- end
@@ -1,80 +0,0 @@
1
- module Yap::Shell::Execution
2
- class RubyCommandExecution < CommandExecution
3
- on_execute do |command:, n:, of:, wait:|
4
- result = nil
5
- stdin, stdout, stderr, world = @stdin, @stdout, @stderr, @world
6
-
7
- exit_code = 0
8
- first_command = n == 1
9
-
10
- f = nil
11
- ruby_result = nil
12
- begin
13
- ruby_command = command.to_executable_str
14
-
15
- Treefell['shell'].puts "ruby execution: reading stdin from #{stdin.inspect}"
16
- contents = if stdin.is_a?(String)
17
- f = File.open stdin
18
- f.read
19
- elsif stdin != $stdin
20
- stdin.read
21
- end
22
-
23
- Treefell['shell'].puts "ruby execution: contents=#{contents.inspect}, setting to world.content"
24
- world.contents = contents
25
-
26
- method = ruby_command.scan(/^(\w+(?:[!?]|\s*=)?)/).flatten.first.gsub(/\s/, '')
27
- Treefell['shell'].puts "ruby execution: method=#{method.inspect}"
28
-
29
- obj = if first_command
30
- world
31
- elsif contents.respond_to?(method)
32
- contents
33
- else
34
- world
35
- end
36
-
37
- if ruby_command =~ /^[A-Z0-9]|::/
38
- Treefell['shell'].puts "ruby executing: eval(#{ruby_command.inspect})"
39
- ruby_result = eval ruby_command
40
- else
41
- ruby_command = "self.#{ruby_command}"
42
- Treefell['shell'].puts "ruby executing: #{obj.class.name} instance instance_eval(#{ruby_command.inspect})"
43
- ruby_result = obj.instance_eval ruby_command
44
- end
45
- rescue Exception => ex
46
- ruby_result = <<-EOT.gsub(/^\s*\S/, '')
47
- |Failed processing ruby: #{ruby_command}
48
- |#{ex}
49
- |#{ex.backtrace.join("\n")}
50
- EOT
51
- exit_code = 1
52
- ensure
53
- f.close if f && !f.closed?
54
- end
55
-
56
- # The next line causes issues sometimes?
57
- # puts "WRITING #{ruby_result.length} bytes" if ENV["DEBUG"]
58
- ruby_result = ruby_result.to_s
59
- ruby_result << "\n" unless ruby_result.end_with?("\n")
60
-
61
- stdout.write ruby_result
62
- stdout.flush
63
- stderr.flush
64
-
65
- stdout.close if stdout != $stdout && !stdout.closed?
66
- stderr.close if stderr != $stderr && !stderr.closed?
67
-
68
- # Pass current execution to give any other threads a chance
69
- # to be scheduled before we send back our status code. This could
70
- # probably use a more elaborate signal or message passing scheme,
71
- # but that's for another day.
72
- # Thread.pass
73
-
74
- # Make up an exit code
75
- Result.new(status_code:exit_code, directory:Dir.pwd, n:n, of:of).tap do |result|
76
- Treefell['shell'].puts "ruby execution done with result=#{result.inspect}"
77
- end
78
- end
79
- end
80
- end
@@ -1,30 +0,0 @@
1
- module Yap::Shell::Execution
2
- class ShellCommandExecution < CommandExecution
3
- on_execute do |command:, n:, of:, wait:|
4
- Treefell['shell'].puts "shell command execution: #{command}"
5
-
6
- possible_parameters = {
7
- command: command.str,
8
- args: command.args,
9
- stdin: (@stdin != $stdin ? @stdin : StringIO.new),
10
- stdout: @stdout,
11
- stderr: @stderr,
12
- world: @world,
13
- line: command.line
14
- }
15
-
16
- func = command.to_proc
17
- params = func.parameters.reduce({}) do |h, (type, name)|
18
- h[name] = possible_parameters[name]
19
- h
20
- end
21
-
22
- Treefell['shell'].puts "shell command executing with params: #{params.inspect} $stdout=#{$stdout.inspect} $stderr=#{$stderr.inspect}"
23
- func.call(**params)
24
-
25
- @stdout.close if @stdout != $stdout && !@stdout.closed?
26
- @stderr.close if @stderr != $stderr && !@stderr.closed?
27
- @stdin.close if @stdin != $stdin && !@stdin.closed?
28
- end
29
- end
30
- end
@@ -1,21 +0,0 @@
1
- module Yap::Shell
2
- class Prompt
3
- attr_reader :text
4
-
5
- def initialize(text:, &blk)
6
- @text = text
7
- @blk = blk
8
- end
9
-
10
- def text=(text)
11
- @text = text
12
- end
13
-
14
- def update
15
- if @blk
16
- @text = @blk.call
17
- end
18
- self
19
- end
20
- end
21
- end
@@ -1,237 +0,0 @@
1
- require 'shellwords'
2
- require 'term/ansicolor'
3
-
4
- module Yap::Shell
5
- module Color
6
- extend Term::ANSIColor
7
- end
8
-
9
- class Repl
10
- attr_reader :editor
11
-
12
- def initialize(world:nil)
13
- @world = world
14
- @editor= world.editor
15
-
16
- Treefell['shell'].puts "installing default keybindings"
17
- install_default_keybindings
18
-
19
- Treefell['shell'].puts "installing default tab completion"
20
- install_default_tab_completion_proc
21
- end
22
-
23
- def on_input(&blk)
24
- @blk = blk
25
-
26
- @world.editor.on_read_line do |event|
27
- line_read = event[:payload][:line]
28
- Treefell['shell'].puts "editor line read: #{line_read.inspect}"
29
- # editor.history = true?
30
- line = line_read << "\n"
31
- begin
32
- @blk.call(line)
33
- rescue Yap::Shell::Parser::Lexer::NonterminatedString,
34
- Yap::Shell::Parser::Lexer::LineContinuationFound => ex
35
- Treefell['shell'].puts "rescued #{ex}, asking user for more input"
36
- more_input = read_another_line_of_input
37
- if more_input
38
- line << more_input
39
- retry
40
- end
41
- rescue ::Yap::Shell::Parser::ParseError => ex
42
- Treefell['shell'].puts "rescued #{ex}, telling user"
43
- puts " Parse error: #{ex.message}"
44
- end
45
-
46
- ensure_process_group_controls_the_tty
47
- @world.refresh_prompt
48
- end
49
- end
50
-
51
- private
52
-
53
- def read_another_line_of_input
54
- print @world.secondary_prompt.update.text
55
- gets
56
- end
57
-
58
- def kill_ring
59
- @kill_ring ||= []
60
- end
61
-
62
- def install_default_keybindings
63
- editor.terminal.keys.merge!(enter: [13])
64
- editor.bind(:return){ editor.newline }
65
-
66
- # Move to beginning of line
67
- editor.bind(:ctrl_a) { editor.move_to_beginning_of_input }
68
-
69
- # Move to end of line
70
- editor.bind(:ctrl_e) { editor.move_to_end_of_input }
71
-
72
- # Move backward one word at a time
73
- editor.bind(:ctrl_b) {
74
- text = editor.line.text[0...editor.line.position].reverse
75
- position = text.index(/\s+/, 1)
76
- position = position ? (text.length - position) : 0
77
- editor.move_to_position position
78
- }
79
-
80
- # Move forward one word at a time
81
- editor.bind(:ctrl_f) {
82
- text = editor.line.text
83
- position = text.index(/\s+/, editor.line.position)
84
- position = position ? (position + 1) : text.length
85
- editor.move_to_position position
86
- }
87
-
88
- # Yank text from the kill ring and insert it at the cursor position
89
- editor.bind(:ctrl_y){
90
- text = kill_ring[-1]
91
- if text
92
- editor.yank_forward text.without_ansi
93
- end
94
- }
95
-
96
- # Backwards delete one word
97
- editor.bind(:ctrl_w){
98
- before_text = editor.line.text[0...editor.line.position]
99
- after_text = editor.line.text[editor.line.position..-1]
100
-
101
- have_only_seen_whitespace = true
102
- position = 0
103
-
104
- before_text.reverse.each_char.with_index do |ch, i|
105
- if ch =~ /\s/ && !have_only_seen_whitespace
106
- position = before_text.length - i
107
- break
108
- else
109
- have_only_seen_whitespace = false
110
- end
111
- end
112
-
113
- killed_text = before_text[position...editor.line.position]
114
- kill_ring.push killed_text
115
-
116
- text = [before_text.slice(0, position), after_text].join
117
- editor.overwrite_line text
118
- editor.move_to_position position
119
- }
120
-
121
- # History forward, but if at the end of the history then give user a
122
- # blank line rather than remain on the last command
123
- editor.bind(:down_arrow) {
124
- if editor.history.searching? && !editor.history.end?
125
- editor.history_forward
126
- else
127
- editor.overwrite_line ""
128
- end
129
- }
130
-
131
- editor.bind(:enter) { editor.newline }
132
- editor.bind(:tab) { editor.complete }
133
- editor.bind(:backspace) { editor.delete_left_character }
134
-
135
- # Delete to end of line from cursor position
136
- editor.bind(:ctrl_k) {
137
- kill_ring.push editor.kill_forward
138
- }
139
-
140
- # Delete to beginning of line from cursor position
141
- editor.bind(:ctrl_u) {
142
- kill_ring.push editor.line.text[0...editor.line.position]
143
- editor.overwrite_line editor.line.text[editor.line.position..-1]
144
- editor.move_to_position 0
145
- }
146
-
147
- # Forward delete a character, leaving the cursor in place
148
- editor.bind("\e[3~") {
149
- before_text = editor.line.text[0...editor.line.position]
150
- after_text = editor.line.text[(editor.line.position+1)..-1]
151
- text = [before_text, after_text].join
152
- position = editor.line.position
153
- editor.overwrite_line text
154
- editor.move_to_position position
155
- }
156
-
157
- editor.bind(:ctrl_l){
158
- editor.clear_screen
159
- }
160
-
161
- editor.bind(:ctrl_r) {
162
- $r = $r ? false : true
163
- # editor.redo
164
- }
165
- editor.bind(:left_arrow) { editor.move_left }
166
- editor.bind(:right_arrow) { editor.move_right }
167
- editor.bind(:up_arrow) { editor.history_back }
168
- editor.bind(:down_arrow) { editor.history_forward }
169
- editor.bind(:delete) { editor.delete_character }
170
- editor.bind(:insert) { editor.toggle_mode }
171
-
172
- editor.bind(:ctrl_g) { editor.clear_history }
173
- # editor.bind(:ctrl_l) { editor.debug_line }
174
- editor.bind(:ctrl_h) { editor.show_history }
175
- editor.bind(:ctrl_d) { puts; puts "Exiting..."; exit }
176
-
177
- # character-search; wraps around as necessary
178
- editor.bind(:ctrl_n) {
179
- line = editor.line
180
- text, start_position = line.text, line.position
181
- i, new_position = start_position, nil
182
-
183
- break_on_bytes = [editor.terminal.keys[:ctrl_c]].flatten
184
- byte = [editor.read_character].flatten.first
185
-
186
- unless break_on_bytes.include?(byte)
187
- loop do
188
- i += 1
189
- i = 0 if i >= text.length # wrap-around to the beginning
190
- break if i == start_position # back to where we started
191
- (editor.move_to_position(i) ; break) if text[i] == byte.chr # found a match; move and break
192
- end
193
- end
194
- }
195
- end
196
-
197
- def install_default_tab_completion_proc
198
- editor.completion_proc = lambda do |word, line, word_index|
199
- Dir["#{word}*"].map{ |str| str.gsub(/ /, '\ ')}
200
- end
201
- end
202
-
203
- # This is to prevent the Errno::EIO error from occurring by ensuring that
204
- # if we haven't been made the process group controlling the TTY that we
205
- # become so. This method intentionally blocks.
206
- def ensure_process_group_controls_the_tty
207
- return unless STDIN.isatty
208
-
209
- tty_pgrp = Termios.tcgetpgrp(STDIN)
210
- while ![Process.pid, Process.getpgrp].include?(tty_pgrp)
211
- Termios.tcsetpgrp(STDIN, Process.pid)
212
- sleep 0.1
213
- end
214
- end
215
-
216
- def process_heredoc(_input)
217
- if _input =~ /<<-?([A-z0-9\-]+)\s*$/
218
- input = _input.dup
219
- marker = $1
220
- input << "\n"
221
- else
222
- return _input
223
- end
224
-
225
- Treefell['shell'].puts "asking for heredoc input with @world.secondary_prompt"
226
- loop do
227
- str = editor.read(@world.secondary_prompt.update.text, false)
228
- input << "#{str}\n"
229
- if str =~ /^#{Regexp.escape(marker)}$/
230
- Treefell['shell'].puts "done asking for heredoc input"
231
- break
232
- end
233
- end
234
- input
235
- end
236
- end
237
- end
@@ -1,5 +0,0 @@
1
- module Yap
2
- module Shell
3
- VERSION = "0.7.1"
4
- end
5
- end
@@ -1,286 +0,0 @@
1
- require 'term/ansicolor'
2
- require 'fileutils'
3
- require 'forwardable'
4
- require 'rawline'
5
- require 'termios'
6
-
7
- module Yap
8
- require 'yap/addon'
9
- require 'yap/shell/execution'
10
- require 'yap/shell/prompt'
11
-
12
- class World
13
- include Term::ANSIColor
14
- extend Forwardable
15
-
16
- DEFAULTS = {
17
- primary_prompt_text: "yap> ",
18
- secondary_prompt_text: "> "
19
- }
20
-
21
- attr_accessor :prompt, :secondary_prompt, :contents, :repl, :editor, :env
22
- attr_reader :addons
23
-
24
- attr_accessor :last_result
25
-
26
- def self.instance(*args)
27
- @instance ||= new(*args)
28
- end
29
-
30
- def initialize(addons:)
31
- @env = ENV.to_h.dup
32
- dom = build_editor_dom
33
-
34
- # ensure yap directory exists
35
- if !File.exists?(configuration.yap_path)
36
- if configuration.skip_first_time?
37
- # skipping first time
38
- else
39
- puts
40
- puts yellow("Yap directory not found: #{configuration.yap_path}")
41
- puts
42
- puts "Initializing yap for the first time:"
43
- puts
44
-
45
- print " Creating #{configuration.yap_path} "
46
- FileUtils.mkdir_p configuration.yap_path
47
- puts green("done")
48
-
49
- print " Creating default #{configuration.preferred_yaprc_path} "
50
- FileUtils.cp configuration.yaprc_template_path, configuration.yap_path
51
- puts green("done")
52
- puts
53
- puts "To tweak yap take a look at #{configuration.preferred_yaprc_path}."
54
- puts
55
- puts "Reloading shell"
56
- reload!
57
- end
58
- end
59
-
60
- @editor = RawLine::Editor.create(dom: dom)
61
-
62
- self.prompt = Yap::Shell::Prompt.new(text: DEFAULTS[:primary_prompt_text])
63
- self.secondary_prompt = Yap::Shell::Prompt.new(text: DEFAULTS[:secondary_prompt_text])
64
-
65
- @repl = Yap::Shell::Repl.new(world:self)
66
-
67
- @addons_initialized = []
68
- @addons = AddonHash.new(
69
- self
70
- )
71
-
72
- addons.each do |addon|
73
- if addon.yap_enabled?
74
- @addons[addon.export_as] = addon
75
- end
76
- end
77
-
78
- @addons.values.select(&:yap_enabled?).each do |addon|
79
- initialize_addon(addon) unless addon_initialized?(addon)
80
- addon
81
- end
82
- end
83
-
84
- def addon_initialized?(addon)
85
- (@addons_initialized ||= []).include?(addon)
86
- end
87
-
88
- def initialize_addon(addon)
89
- return unless addon
90
- begin
91
- addon.initialize_world(self)
92
- (@addons_initialized ||= []) << addon
93
- rescue Exception => ex
94
- puts Term::ANSIColor.red(("The #{addon.addon_name} addon failed to initialize due to error:"))
95
- puts ex.message
96
- puts ex.backtrace[0..5]
97
- end
98
- end
99
-
100
- class AddonHash < Hash
101
- def initialize(world)
102
- @world = world
103
- end
104
-
105
- def [](key)
106
- addon = super
107
- unless @world.addon_initialized?(addon)
108
- @world.initialize_addon(addon)
109
- end
110
- addon
111
- end
112
- end
113
-
114
- def configuration
115
- ::Yap.configuration
116
- end
117
-
118
- def [](addon_name)
119
- @addons.fetch(addon_name){ raise(ArgumentError, "No addon loaded registered as #{addon_name}") }
120
- end
121
-
122
- def aliases
123
- Yap::Shell::Aliases.instance
124
- end
125
-
126
- def builtins
127
- Yap::Shell::BuiltinCommand.builtins.keys.map(&:to_s)
128
- end
129
-
130
- def shell_commands
131
- Yap::Shell::ShellCommand.registered_functions.keys.map(&:to_s)
132
- end
133
-
134
- def events
135
- @editor.events
136
- end
137
-
138
- def bind(key, &blk)
139
- @editor.bind(key) do
140
- blk.call self
141
- end
142
- end
143
-
144
- def unbind(key)
145
- @editor.unbind(key)
146
- end
147
-
148
- def reload!
149
- exec configuration.yap_binpath
150
- end
151
-
152
- def func(name, &blk)
153
- Yap::Shell::ShellCommand.define_shell_function(name, &blk)
154
- end
155
-
156
- def shell(statement)
157
- context = Yap::Shell::Execution::Context.new(
158
- stdin: $stdin,
159
- stdout: $stdout,
160
- stderr: $stderr
161
- )
162
- if statement.nil?
163
- @last_result = Yap::Shell::Execution::Result.new(
164
- status_code: 1,
165
- directory: Dir.pwd,
166
- n: 1,
167
- of: 1
168
- )
169
- else
170
- evaluation = Yap::Shell::Evaluation.new(stdin:$stdin, stdout:$stdout, stderr:$stderr, world:self)
171
- evaluation.evaluate(statement) do |command, stdin, stdout, stderr, wait|
172
- context.clear_commands
173
- context.add_command_to_run command, stdin:stdin, stdout:stdout, stderr:stderr, wait:wait
174
- @last_result = context.execute(world:self) || 0
175
- if @last_result.is_a?(Integer)
176
- Yap::Shell::Execution::Result.new(
177
- status_code: @last_result,
178
- directory: Dir.pwd,
179
- n: 1,
180
- of: 1
181
- )
182
- else
183
- @last_result
184
- end
185
- end
186
- end
187
-
188
- @last_result
189
- end
190
-
191
- def foreground?
192
- return unless STDIN.isatty
193
- Process.getpgrp == Termios.tcgetpgrp($stdout)
194
- end
195
-
196
- def history
197
- @editor.history
198
- end
199
-
200
- def interactive!
201
- refresh_prompt
202
- @editor.start
203
- end
204
-
205
- def prompt
206
- @prompt
207
- end
208
-
209
- def prompt=(prompt=nil, &blk)
210
- if prompt.is_a?(Yap::Shell::Prompt)
211
- @prompt = prompt
212
- elsif prompt.respond_to?(:call) # proc
213
- @prompt = Yap::Shell::Prompt.new(text:prompt.call, &prompt)
214
- else # text
215
- @prompt = Yap::Shell::Prompt.new(text:prompt, &blk)
216
- end
217
- end
218
-
219
- def secondary_prompt=(prompt=nil, &blk)
220
- if prompt.is_a?(Yap::Shell::Prompt)
221
- @secondary_prompt = prompt
222
- elsif prompt.respond_to?(:call) # proc
223
- @secondary_prompt = Yap::Shell::Prompt.new(text:prompt.call, &prompt)
224
- else # text
225
- @secondary_prompt = Yap::Shell::Prompt.new(text:prompt, &blk)
226
- end
227
- end
228
-
229
- def refresh_prompt
230
- @editor.prompt = @prompt.update.text
231
- end
232
-
233
- def right_prompt_text=(str)
234
- @right_status_float.width = str.length
235
- @right_status_box.content = str
236
- end
237
-
238
- def subscribe(*args, &blk)
239
- @editor.subscribe(*args, &blk)
240
- end
241
-
242
- def build_editor_dom
243
- @left_status_box = TerminalLayout::Box.new(content: "", style: {display: :inline})
244
- @right_status_box = TerminalLayout::Box.new(content: "", style: {display: :inline})
245
- @prompt_box = TerminalLayout::Box.new(content: "yap>", style: {display: :inline})
246
- @input_box = TerminalLayout::InputBox.new(content: "", style: {display: :inline})
247
-
248
- @content_box = TerminalLayout::Box.new(content: "", style: {display: :block})
249
- @bottom_left_status_box = TerminalLayout::Box.new(content: "", style: {display: :inline})
250
- @bottom_right_status_box = TerminalLayout::Box.new(content: "", style: {display: :inline})
251
-
252
- @right_status_float = TerminalLayout::Box.new(style: {display: :float, float: :right, width: @right_status_box.content.length},
253
- children: [
254
- @right_status_box
255
- ]
256
- )
257
-
258
- RawLine::DomTree.new(
259
- children:[
260
- @right_status_float,
261
- @left_status_box,
262
- @prompt_box,
263
- @input_box,
264
- @content_box,
265
- TerminalLayout::Box.new(style: {display: :float, float: :left, width: @bottom_left_status_box.content.length},
266
- children: [
267
- @bottom_left_status_box
268
- ]
269
- ),
270
- TerminalLayout::Box.new(style: {display: :float, float: :right, width: @bottom_right_status_box.content.length},
271
- children: [
272
- @bottom_right_status_box
273
- ]
274
- )
275
- ]
276
- ).tap do |dom|
277
- dom.prompt_box = @prompt_box
278
- dom.input_box = @input_box
279
- dom.content_box = @content_box
280
- @prompt_box.name = "prompt-box"
281
- @input_box.name = "input-box"
282
- @content_box.name = "content-box"
283
- end
284
- end
285
- end
286
- end