diff options
-rw-r--r-- | zellij-client/src/input_handler.rs | 14 | ||||
-rw-r--r-- | zellij-client/src/lib.rs | 50 | ||||
-rw-r--r-- | zellij-client/src/stdin_ansi_parser.rs | 3 | ||||
-rw-r--r-- | zellij-client/src/stdin_handler.rs | 19 | ||||
-rw-r--r-- | zellij-utils/src/errors.rs | 2 |
5 files changed, 85 insertions, 3 deletions
diff --git a/zellij-client/src/input_handler.rs b/zellij-client/src/input_handler.rs index 801ff0951..bf3bcc006 100644 --- a/zellij-client/src/input_handler.rs +++ b/zellij-client/src/input_handler.rs @@ -147,6 +147,20 @@ impl InputHandler { self.handle_stdin_ansi_instruction(ansi_instruction); } }, + Ok((InputInstruction::StartedParsing, _error_context)) => { + log::info!("sending done loading"); + self.send_client_instructions + .send(ClientInstruction::StartedParsingStdinQuery) + .unwrap(); + log::info!("done sent done loading"); + }, + Ok((InputInstruction::DoneParsing, _error_context)) => { + log::info!("sending done loading"); + self.send_client_instructions + .send(ClientInstruction::DoneParsingStdinQuery) + .unwrap(); + log::info!("done sent done loading"); + }, Err(err) => panic!("Encountered read error: {:?}", err), } } diff --git a/zellij-client/src/lib.rs b/zellij-client/src/lib.rs index 0fd549ab4..51d6c99d6 100644 --- a/zellij-client/src/lib.rs +++ b/zellij-client/src/lib.rs @@ -43,6 +43,8 @@ pub(crate) enum ClientInstruction { SwitchToMode(InputMode), Connected, ActiveClients(Vec<ClientId>), + StartedParsingStdinQuery, + DoneParsingStdinQuery, } impl From<ServerToClientMsg> for ClientInstruction { @@ -70,6 +72,8 @@ impl From<&ClientInstruction> for ClientContext { ClientInstruction::SwitchToMode(_) => ClientContext::SwitchToMode, ClientInstruction::Connected => ClientContext::Connected, ClientInstruction::ActiveClients(_) => ClientContext::ActiveClients, + ClientInstruction::StartedParsingStdinQuery => ClientContext::StartedParsingStdinQuery, + ClientInstruction::DoneParsingStdinQuery => ClientContext::DoneParsingStdinQuery, } } } @@ -121,6 +125,8 @@ pub(crate) enum InputInstruction { KeyEvent(InputEvent, Vec<u8>), SwitchToMode(InputMode), AnsiStdinInstructions(Vec<AnsiStdinInstruction>), + StartedParsing, + DoneParsing, } pub fn start_client( @@ -337,13 +343,51 @@ pub fn start_client( }; let exit_msg: String; + let mut loading = true; + let mut pending_instructions = vec![]; + + let mut stdout = os_input.get_stdout_writer(); + stdout + .write_all("\u{1b}[1mLoading Zellij\u{1b}[m".as_bytes()) + .expect("cannot write to stdout"); + stdout.flush().expect("could not flush"); loop { - let (client_instruction, mut err_ctx) = receive_client_instructions - .recv() - .expect("failed to receive app instruction on channel"); + let (client_instruction, mut err_ctx) = if !loading && !pending_instructions.is_empty() { + // there are buffered instructions, we need to go through them before processing the + // new ones + pending_instructions.remove(0) + } else { + receive_client_instructions + .recv() + .expect("failed to receive app instruction on channel") + }; + + if loading { + // when the app is still loading, we buffer instructions and show a loading screen + match client_instruction { + ClientInstruction::StartedParsingStdinQuery => { + stdout + .write_all("\n\rQuerying terminal emulator for \u{1b}[32;1mdefault colors\u{1b}[m and \u{1b}[32;1mpixel/cell\u{1b}[m ratio...".as_bytes()) + .expect("cannot write to stdout"); + stdout.flush().expect("could not flush"); + }, + ClientInstruction::DoneParsingStdinQuery => { + stdout + .write_all("done".as_bytes()) + .expect("cannot write to stdout"); + stdout.flush().expect("could not flush"); + loading = false; + }, + instruction => { + pending_instructions.push((instruction, err_ctx)); + }, + } + continue; + } err_ctx.add_call(ContextType::Client((&client_instruction).into())); + match client_instruction { ClientInstruction::Exit(reason) => { os_input.send_to_server(ClientToServerMsg::ClientExited); diff --git a/zellij-client/src/stdin_ansi_parser.rs b/zellij-client/src/stdin_ansi_parser.rs index 09247bf9b..23e869b2b 100644 --- a/zellij-client/src/stdin_ansi_parser.rs +++ b/zellij-client/src/stdin_ansi_parser.rs @@ -73,6 +73,9 @@ impl StdinAnsiParser { } false } + pub fn startup_query_duration(&self) -> u64 { + STARTUP_PARSE_DEADLINE_MS + } pub fn parse(&mut self, mut raw_bytes: Vec<u8>) -> Vec<AnsiStdinInstruction> { for byte in raw_bytes.drain(..) { self.parse_byte(byte); diff --git a/zellij-client/src/stdin_handler.rs b/zellij-client/src/stdin_handler.rs index 8d6e51b0a..75634a05b 100644 --- a/zellij-client/src/stdin_handler.rs +++ b/zellij-client/src/stdin_handler.rs @@ -5,6 +5,20 @@ use std::sync::{Arc, Mutex}; use zellij_utils::channels::SenderWithContext; use zellij_utils::termwiz::input::{InputEvent, InputParser, MouseButtons}; +fn send_done_parsing_after_query_timeout( + send_input_instructions: SenderWithContext<InputInstruction>, + query_duration: u64, +) { + std::thread::spawn({ + move || { + std::thread::sleep(std::time::Duration::from_millis(query_duration)); + send_input_instructions + .send(InputInstruction::DoneParsing) + .unwrap(); + } + }); +} + pub(crate) fn stdin_loop( mut os_input: Box<dyn ClientOsApi>, send_input_instructions: SenderWithContext<InputInstruction>, @@ -15,6 +29,9 @@ pub(crate) fn stdin_loop( let mut current_buffer = vec![]; // on startup we send a query to the terminal emulator for stuff like the pixel size and colors // we get a response through STDIN, so it makes sense to do this here + send_input_instructions + .send(InputInstruction::StartedParsing) + .unwrap(); let terminal_emulator_query_string = stdin_ansi_parser .lock() .unwrap() @@ -23,6 +40,8 @@ pub(crate) fn stdin_loop( .get_stdout_writer() .write(terminal_emulator_query_string.as_bytes()) .unwrap(); + let query_duration = stdin_ansi_parser.lock().unwrap().startup_query_duration(); + send_done_parsing_after_query_timeout(send_input_instructions.clone(), query_duration); loop { let buf = os_input.read_from_stdin(); { diff --git a/zellij-utils/src/errors.rs b/zellij-utils/src/errors.rs index 07947dd12..70d4b3f6d 100644 --- a/zellij-utils/src/errors.rs +++ b/zellij-utils/src/errors.rs @@ -384,6 +384,8 @@ pub enum ClientContext { Connected, ActiveClients, OwnClientId, + StartedParsingStdinQuery, + DoneParsingStdinQuery, } /// Stack call representations corresponding to the different types of [`ServerInstruction`]s. |