yap-shell 0.7.1 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
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