Class: RuVim::StreamMixer
- Inherits:
-
Object
- Object
- RuVim::StreamMixer
- Defined in:
- lib/ruvim/stream_mixer.rb
Constant Summary collapse
- LARGE_FILE_ASYNC_THRESHOLD_BYTES =
64 * 1024 * 1024
- LARGE_FILE_STAGED_PREFIX_BYTES =
8 * 1024 * 1024
Instance Method Summary collapse
- #drain_events! ⇒ Object
- #ensure_event_queue! ⇒ Object
- #ex_follow_toggle ⇒ Object
- #follow_active?(buf) ⇒ Boolean
-
#initialize(editor:, signal_w:) ⇒ StreamMixer
constructor
A new instance of StreamMixer.
- #open_path_with_large_file_support(path) ⇒ Object
- #prepare_stdin_stream_buffer!(io) ⇒ Object
- #shutdown! ⇒ Object
- #start_command_stream!(buf, command) ⇒ Object
- #start_follow!(buf) ⇒ Object
- #start_git_stream_command(buffer_id, cmd, root) ⇒ Object
- #start_pending_stdin! ⇒ Object
- #stop_buffer_stream!(buf) ⇒ Object
- #stop_follow!(buf) ⇒ Object
- #stop_git_stream!(buffer_id) ⇒ Object
Constructor Details
#initialize(editor:, signal_w:) ⇒ StreamMixer
Returns a new instance of StreamMixer.
8 9 10 11 12 |
# File 'lib/ruvim/stream_mixer.rb', line 8 def initialize(editor:, signal_w:) @editor = editor @signal_w = signal_w @stream_event_queue = nil end |
Instance Method Details
#drain_events! ⇒ Object
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/ruvim/stream_mixer.rb', line 75 def drain_events! return false unless @stream_event_queue changed = false loop do event = @stream_event_queue.pop(true) case event[:type] when :stream_data changed = apply_stream_chunk!(event[:buffer_id], event[:data]) || changed when :stream_eof changed = finish_stream!(event[:buffer_id], status: event[:status]) || changed when :stream_error changed = fail_stream!(event[:buffer_id], event[:error]) || changed when :follow_data changed = apply_stream_chunk!(event[:buffer_id], event[:data]) || changed when :follow_truncated if (buf = @editor.buffers[event[:buffer_id]]) @editor.echo("[follow] file truncated: #{buf.display_name}") changed = true end when :follow_deleted if (buf = @editor.buffers[event[:buffer_id]]) @editor.echo("[follow] file deleted, waiting for re-creation: #{buf.display_name}") changed = true end when :file_lines changed = apply_async_file_lines!(event[:buffer_id], event[:head], event[:lines], loaded_bytes: event[:loaded_bytes], file_size: event[:file_size]) || changed when :file_eof changed = finish_async_file_load!(event[:buffer_id], ended_with_newline: event[:ended_with_newline]) || changed when :file_error changed = fail_async_file_load!(event[:buffer_id], event[:error]) || changed end end rescue ThreadError changed end |
#ensure_event_queue! ⇒ Object
181 182 183 |
# File 'lib/ruvim/stream_mixer.rb', line 181 def ensure_event_queue! @stream_event_queue ||= Queue.new end |
#ex_follow_toggle ⇒ Object
112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/ruvim/stream_mixer.rb', line 112 def ex_follow_toggle buf = @editor.current_buffer raise RuVim::CommandError, "No file associated with buffer" unless buf.path if buf.stream.is_a?(Stream::Follow) stop_follow!(buf) else raise RuVim::CommandError, "Buffer has unsaved changes" if buf.modified? start_follow!(buf) end end |
#follow_active?(buf) ⇒ Boolean
162 163 164 |
# File 'lib/ruvim/stream_mixer.rb', line 162 def follow_active?(buf) buf.stream.is_a?(Stream::Follow) end |
#open_path_with_large_file_support(path) ⇒ Object
166 167 168 169 170 171 |
# File 'lib/ruvim/stream_mixer.rb', line 166 def open_path_with_large_file_support(path) return @editor.open_path_sync(path) unless should_open_path_async?(path) return @editor.open_path_sync(path) unless can_start_async_file_load? open_path_asynchronously!(path) end |
#prepare_stdin_stream_buffer!(io) ⇒ Object
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/ruvim/stream_mixer.rb', line 14 def prepare_stdin_stream_buffer!(io) buf = @editor.current_buffer if buf.intro_buffer? @editor.materialize_intro_buffer! buf = @editor.current_buffer end buf.replace_all_lines!([""]) buf.configure_special!(kind: :stream, name: "[stdin]", readonly: true, modifiable: false) buf.modified = false buf.["filetype"] = "text" ensure_event_queue! move_window_to_stream_end!(@editor.current_window, buf) @editor.echo("[stdin] follow") @pending_stdin = { buf: buf, io: io } buf end |
#shutdown! ⇒ Object
173 174 175 176 177 178 179 |
# File 'lib/ruvim/stream_mixer.rb', line 173 def shutdown! @editor.buffers.each_value do |buf| buf.stream&.stop! rescue StandardError nil end end |
#start_command_stream!(buf, command) ⇒ Object
45 46 47 48 49 50 51 |
# File 'lib/ruvim/stream_mixer.rb', line 45 def start_command_stream!(buf, command) ensure_event_queue! buf.stream = Stream::Run.new( command: command, buffer_id: buf.id, queue: @stream_event_queue, stop_handler: -> { stop_buffer_stream!(buf) }, &method(:notify_signal_wakeup) ) end |
#start_follow!(buf) ⇒ Object
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/ruvim/stream_mixer.rb', line 124 def start_follow!(buf) ensure_event_queue! Buffer.ensure_regular_file!(buf.path) if buf.path if buf.path && File.file?(buf.path) data = File.binread(buf.path) if data.end_with?("\n") && buf.lines.last.to_s != "" following_wins = @editor.windows.values.select do |w| w.buffer_id == buf.id && stream_window_following_end?(w, buf) end buf.append_stream_text!("\n") following_wins.each { |w| move_window_to_stream_end!(w, buf) } end end buf.stream = Stream::Follow.new( path: buf.path, buffer_id: buf.id, queue: @stream_event_queue, stop_handler: -> { stop_follow!(buf) }, &method(:notify_signal_wakeup) ) @editor.echo("[follow] #{buf.display_name}") end |
#start_git_stream_command(buffer_id, cmd, root) ⇒ Object
53 54 55 56 57 58 59 |
# File 'lib/ruvim/stream_mixer.rb', line 53 def start_git_stream_command(buffer_id, cmd, root) ensure_event_queue! buf = @editor.buffers[buffer_id] return unless buf buf.stream = Stream::Git.new(cmd: cmd, root: root, buffer_id: buffer_id, queue: @stream_event_queue, &method(:notify_signal_wakeup)) end |
#start_pending_stdin! ⇒ Object
32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/ruvim/stream_mixer.rb', line 32 def start_pending_stdin! return unless @pending_stdin ps = @pending_stdin @pending_stdin = nil buf = ps[:buf] ensure_event_queue! buf.stream = Stream::Stdin.new( io: ps[:io], buffer_id: buf.id, queue: @stream_event_queue, stop_handler: -> { stop_buffer_stream!(buf) }, &method(:notify_signal_wakeup) ) end |
#stop_buffer_stream!(buf) ⇒ Object
61 62 63 64 65 66 67 68 |
# File 'lib/ruvim/stream_mixer.rb', line 61 def stop_buffer_stream!(buf) return false unless buf&.stream&.live? buf.stream.stop! @editor.echo("#{buf.display_name} stopped") notify_signal_wakeup true end |
#stop_follow!(buf) ⇒ Object
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/ruvim/stream_mixer.rb', line 146 def stop_follow!(buf) buf.stream&.stop! # Remove trailing empty line added as sentinel by start_follow! if buf.line_count > 1 && buf.lines.last.to_s == "" buf.lines.pop last = buf.line_count - 1 @editor.windows.each_value do |win| next unless win.buffer_id == buf.id win.cursor_y = last if win.cursor_y > last end end buf.stream = nil @editor.echo("[follow] stopped") true end |
#stop_git_stream!(buffer_id) ⇒ Object
70 71 72 73 |
# File 'lib/ruvim/stream_mixer.rb', line 70 def stop_git_stream!(buffer_id) buf = @editor.buffers[buffer_id] buf&.stream&.stop! end |