feat(cli): QueryTabNames cli action to list all tab names (#2145)
* extend display char in tab * Add action to list all tab names * print tab names and remove logs * change msg name, and handle Log in normal client * fix log * resolve code conflict * change var name * add snapshot test * fix failed test case * restore snapshot * Revert "restore snapshot" This reverts commit b97a9512ab106615a1a1e5882392a03a17cdf1a3. * restore snapshot * revert snapshot * fix(layout): various parser and ui fixes (#2191) * fix(layout): error on nodes outside layout node * fix(layout): move stacked property to pane * fix(layout): various stack exceptions * fix(ui): non-flexible stacked pane titles now take up their full length * fix(ui): stack titles with no-pane-frames take up their proper length * style(fmt): rustfmt * docs(changelog): layout fixes * fix(messaging): cache hold pane messages by their tab_id if the tab is not ready (#2196) * fix(messaging): cache hold pane messages by their tab_id if the tab is not ready * style(fmt): rustfmt * docs(changelog): open panes fix * fix(layout): tab focus (#2197) * fix(layout): tab focus * style(fmt): rustfmt * docs(changel0g): tab focus fix * fix(cli): new-tab now also looks in layout_dir for layouts (#2198) * fix(cli): the new-tab action now also searches for layouts in the layout dir * style(fmt): rustfmt * fix(tests): add missing parameter to cli action * docs(changelog): new-tab cli layout folder fix * fix(kdl): new-tab keybind looks in layout_dir for layouts (#2200) * fix(themes): missing tokyo-night-dark theme * fix(kdl): new-tab keybind also looks in layout_dir for layouts * docs(changelog): new-tab keybind layout folder fix * fix(cli): edit cwd (#2201) * fix(cli): properly set cwd for edit panes * fix(layouts): properly set cwd for edit panes * style(fmt): rustfmt * docs(changelog0 * fix(layouts): do not relayout twice on auto_layout (#2202) * fix(layouts): do not relayout twice on auto_layout * style(fmt): rustfmt * fix(new-tab): get config parameters from config file (#2203) * fix(cli): take default shell from config if it exists when opening new tab * fix(cli): take layout dir from config when opening new tab if it exists * style(fmt): rustfmt * docs(changelog): new-tab config parameters * fix(grid): only use background pending styling when deleting characters (#2204) * docs(changelog): neovim underline fix * feat(layouts): exact panes constraint (#2206) * style(fmt): remove warnings * fix(swap-layouts): introduce exact panes constraint * fix(swap-layouts): improve floating pane swap layout ux * style(fmt): rustfmt * docs(changelog): exact panes constraint * fix(pty): report no-cwd for empty path returned from sysinfo (#2213) * fix(sixel): report pixel size in winsize change ioctl (#2212) * fix(sixel): report pixel size in winsize change ioctl * style(fmt): rustfmt * docs(changelog): various fixes * style(code): naming * test(log): adjust query tab names test to look at the log message * style(fmt): rustfmt --------- Co-authored-by: Aram Drevekenin <aram@poor.dev> Co-authored-by: Jae-Heon Ji <32578710+jaeheonji@users.noreply.github.com>
This commit is contained in:
parent
715ee1109d
commit
c2fb275319
13 changed files with 103 additions and 2 deletions
|
|
@ -28,6 +28,10 @@ pub fn start_cli_client(os_input: Box<dyn ClientOsApi>, session_name: &str, acti
|
||||||
os_input.send_to_server(ClientToServerMsg::ClientExited);
|
os_input.send_to_server(ClientToServerMsg::ClientExited);
|
||||||
process::exit(0);
|
process::exit(0);
|
||||||
},
|
},
|
||||||
|
Some((ServerToClientMsg::Log(log_lines), _)) => {
|
||||||
|
log_lines.iter().for_each(|line| println!("{line}"));
|
||||||
|
process::exit(0);
|
||||||
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ pub(crate) enum ClientInstruction {
|
||||||
ActiveClients(Vec<ClientId>),
|
ActiveClients(Vec<ClientId>),
|
||||||
StartedParsingStdinQuery,
|
StartedParsingStdinQuery,
|
||||||
DoneParsingStdinQuery,
|
DoneParsingStdinQuery,
|
||||||
|
Log(Vec<String>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ServerToClientMsg> for ClientInstruction {
|
impl From<ServerToClientMsg> for ClientInstruction {
|
||||||
|
|
@ -58,6 +59,7 @@ impl From<ServerToClientMsg> for ClientInstruction {
|
||||||
},
|
},
|
||||||
ServerToClientMsg::Connected => ClientInstruction::Connected,
|
ServerToClientMsg::Connected => ClientInstruction::Connected,
|
||||||
ServerToClientMsg::ActiveClients(clients) => ClientInstruction::ActiveClients(clients),
|
ServerToClientMsg::ActiveClients(clients) => ClientInstruction::ActiveClients(clients),
|
||||||
|
ServerToClientMsg::Log(log_lines) => ClientInstruction::Log(log_lines),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -72,6 +74,7 @@ impl From<&ClientInstruction> for ClientContext {
|
||||||
ClientInstruction::SwitchToMode(_) => ClientContext::SwitchToMode,
|
ClientInstruction::SwitchToMode(_) => ClientContext::SwitchToMode,
|
||||||
ClientInstruction::Connected => ClientContext::Connected,
|
ClientInstruction::Connected => ClientContext::Connected,
|
||||||
ClientInstruction::ActiveClients(_) => ClientContext::ActiveClients,
|
ClientInstruction::ActiveClients(_) => ClientContext::ActiveClients,
|
||||||
|
ClientInstruction::Log(_) => ClientContext::Log,
|
||||||
ClientInstruction::StartedParsingStdinQuery => ClientContext::StartedParsingStdinQuery,
|
ClientInstruction::StartedParsingStdinQuery => ClientContext::StartedParsingStdinQuery,
|
||||||
ClientInstruction::DoneParsingStdinQuery => ClientContext::DoneParsingStdinQuery,
|
ClientInstruction::DoneParsingStdinQuery => ClientContext::DoneParsingStdinQuery,
|
||||||
}
|
}
|
||||||
|
|
@ -406,6 +409,11 @@ pub fn start_client(
|
||||||
.send(InputInstruction::SwitchToMode(input_mode))
|
.send(InputInstruction::SwitchToMode(input_mode))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
},
|
},
|
||||||
|
ClientInstruction::Log(lines_to_log) => {
|
||||||
|
for line in lines_to_log {
|
||||||
|
log::info!("{line}");
|
||||||
|
}
|
||||||
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,7 @@ pub enum ServerInstruction {
|
||||||
AttachClient(ClientAttributes, Options, ClientId),
|
AttachClient(ClientAttributes, Options, ClientId),
|
||||||
ConnStatus(ClientId),
|
ConnStatus(ClientId),
|
||||||
ActiveClients(ClientId),
|
ActiveClients(ClientId),
|
||||||
|
Log(Vec<String>, ClientId),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&ServerInstruction> for ServerContext {
|
impl From<&ServerInstruction> for ServerContext {
|
||||||
|
|
@ -93,6 +94,7 @@ impl From<&ServerInstruction> for ServerContext {
|
||||||
ServerInstruction::AttachClient(..) => ServerContext::AttachClient,
|
ServerInstruction::AttachClient(..) => ServerContext::AttachClient,
|
||||||
ServerInstruction::ConnStatus(..) => ServerContext::ConnStatus,
|
ServerInstruction::ConnStatus(..) => ServerContext::ConnStatus,
|
||||||
ServerInstruction::ActiveClients(_) => ServerContext::ActiveClients,
|
ServerInstruction::ActiveClients(_) => ServerContext::ActiveClients,
|
||||||
|
ServerInstruction::Log(..) => ServerContext::Log,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -623,6 +625,14 @@ pub fn start_server(mut os_input: Box<dyn ServerOsApi>, socket_path: PathBuf) {
|
||||||
session_state
|
session_state
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
ServerInstruction::Log(lines_to_log, client_id) => {
|
||||||
|
send_to_client!(
|
||||||
|
client_id,
|
||||||
|
os_input,
|
||||||
|
ServerToClientMsg::Log(lines_to_log),
|
||||||
|
session_state
|
||||||
|
);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -659,6 +659,12 @@ pub(crate) fn route_action(
|
||||||
.send_to_screen(ScreenInstruction::NextSwapLayout(client_id))
|
.send_to_screen(ScreenInstruction::NextSwapLayout(client_id))
|
||||||
.with_context(err_context)?;
|
.with_context(err_context)?;
|
||||||
},
|
},
|
||||||
|
Action::QueryTabNames => {
|
||||||
|
session
|
||||||
|
.senders
|
||||||
|
.send_to_screen(ScreenInstruction::QueryTabNames(client_id))
|
||||||
|
.with_context(err_context)?;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
Ok(should_break)
|
Ok(should_break)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -248,6 +248,7 @@ pub enum ScreenInstruction {
|
||||||
ClearPaneFrameColorOverride(Vec<PaneId>),
|
ClearPaneFrameColorOverride(Vec<PaneId>),
|
||||||
PreviousSwapLayout(ClientId),
|
PreviousSwapLayout(ClientId),
|
||||||
NextSwapLayout(ClientId),
|
NextSwapLayout(ClientId),
|
||||||
|
QueryTabNames(ClientId),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&ScreenInstruction> for ScreenContext {
|
impl From<&ScreenInstruction> for ScreenContext {
|
||||||
|
|
@ -390,6 +391,7 @@ impl From<&ScreenInstruction> for ScreenContext {
|
||||||
},
|
},
|
||||||
ScreenInstruction::PreviousSwapLayout(..) => ScreenContext::PreviousSwapLayout,
|
ScreenInstruction::PreviousSwapLayout(..) => ScreenContext::PreviousSwapLayout,
|
||||||
ScreenInstruction::NextSwapLayout(..) => ScreenContext::NextSwapLayout,
|
ScreenInstruction::NextSwapLayout(..) => ScreenContext::NextSwapLayout,
|
||||||
|
ScreenInstruction::QueryTabNames(..) => ScreenContext::QueryTabNames,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1171,7 +1173,7 @@ impl Screen {
|
||||||
},
|
},
|
||||||
c => {
|
c => {
|
||||||
// It only allows printable unicode
|
// It only allows printable unicode
|
||||||
if buf.iter().all(|u| matches!(u, 0x20..=0x7E | 0x80..=0xFF)) {
|
if buf.iter().all(|u| matches!(u, 0x20..=0x7E | 0xA0..=0xFF)) {
|
||||||
active_tab.name.push_str(c);
|
active_tab.name.push_str(c);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -2360,6 +2362,17 @@ pub(crate) fn screen_thread_main(
|
||||||
screen.update_tabs()?;
|
screen.update_tabs()?;
|
||||||
screen.unblock_input()?;
|
screen.unblock_input()?;
|
||||||
},
|
},
|
||||||
|
ScreenInstruction::QueryTabNames(client_id) => {
|
||||||
|
let tab_names = screen
|
||||||
|
.get_tabs_mut()
|
||||||
|
.values()
|
||||||
|
.map(|tab| tab.name.clone())
|
||||||
|
.collect::<Vec<String>>();
|
||||||
|
screen
|
||||||
|
.bus
|
||||||
|
.senders
|
||||||
|
.send_to_server(ServerInstruction::Log(tab_names, client_id))?;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -3082,7 +3082,7 @@ impl Tab {
|
||||||
// It only allows printable unicode, delete and backspace keys.
|
// It only allows printable unicode, delete and backspace keys.
|
||||||
let is_updatable = buf
|
let is_updatable = buf
|
||||||
.iter()
|
.iter()
|
||||||
.all(|u| matches!(u, 0x20..=0x7E | 0x80..=0xFF | 0x08 | 0x7F));
|
.all(|u| matches!(u, 0x20..=0x7E | 0xA0..=0xFF | 0x08 | 0x7F));
|
||||||
if is_updatable {
|
if is_updatable {
|
||||||
let s = str::from_utf8(&buf).with_context(err_context)?;
|
let s = str::from_utf8(&buf).with_context(err_context)?;
|
||||||
active_terminal.update_name(s);
|
active_terminal.update_name(s);
|
||||||
|
|
|
||||||
|
|
@ -2674,3 +2674,39 @@ pub fn send_cli_undo_rename_tab() {
|
||||||
*received_plugin_instructions.lock().unwrap()
|
*received_plugin_instructions.lock().unwrap()
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn send_cli_query_tab_names_action() {
|
||||||
|
let size = Size { cols: 80, rows: 10 };
|
||||||
|
let client_id = 10; // fake client id should not appear in the screen's state
|
||||||
|
let mut mock_screen = MockScreen::new(size);
|
||||||
|
mock_screen.new_tab(TiledPaneLayout::default());
|
||||||
|
let session_metadata = mock_screen.clone_session_metadata();
|
||||||
|
let screen_thread = mock_screen.run(Some(TiledPaneLayout::default()));
|
||||||
|
let received_server_instructions = Arc::new(Mutex::new(vec![]));
|
||||||
|
let server_receiver = mock_screen.server_receiver.take().unwrap();
|
||||||
|
let server_thread = log_actions_in_thread!(
|
||||||
|
received_server_instructions,
|
||||||
|
ServerInstruction::KillSession,
|
||||||
|
server_receiver
|
||||||
|
);
|
||||||
|
let query_tab_names = CliAction::QueryTabNames;
|
||||||
|
send_cli_action_to_server(
|
||||||
|
&session_metadata,
|
||||||
|
query_tab_names,
|
||||||
|
&mut mock_screen,
|
||||||
|
client_id,
|
||||||
|
);
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||||
|
mock_screen.teardown(vec![server_thread, screen_thread]);
|
||||||
|
let log_tab_names_instruction = received_server_instructions
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.find(|instruction| match instruction {
|
||||||
|
ServerInstruction::Log(..) => true,
|
||||||
|
_ => false,
|
||||||
|
})
|
||||||
|
.cloned();
|
||||||
|
assert_snapshot!(format!("{:#?}", log_tab_names_instruction));
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
source: zellij-server/src/./unit/screen_tests.rs
|
||||||
|
assertion_line: 2713
|
||||||
|
expression: "format!(\"{:#?}\", log_tab_names_action)"
|
||||||
|
---
|
||||||
|
Some(
|
||||||
|
Log(
|
||||||
|
[
|
||||||
|
"Tab #1",
|
||||||
|
"Tab #2",
|
||||||
|
],
|
||||||
|
10,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
@ -366,4 +366,6 @@ pub enum CliAction {
|
||||||
},
|
},
|
||||||
PreviousSwapLayout,
|
PreviousSwapLayout,
|
||||||
NextSwapLayout,
|
NextSwapLayout,
|
||||||
|
/// Query all tab names
|
||||||
|
QueryTabNames,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -323,6 +323,7 @@ pub enum ScreenContext {
|
||||||
ClearPaneFrameColorOverride,
|
ClearPaneFrameColorOverride,
|
||||||
PreviousSwapLayout,
|
PreviousSwapLayout,
|
||||||
NextSwapLayout,
|
NextSwapLayout,
|
||||||
|
QueryTabNames,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stack call representations corresponding to the different types of [`PtyInstruction`]s.
|
/// Stack call representations corresponding to the different types of [`PtyInstruction`]s.
|
||||||
|
|
@ -366,6 +367,7 @@ pub enum ClientContext {
|
||||||
SwitchToMode,
|
SwitchToMode,
|
||||||
Connected,
|
Connected,
|
||||||
ActiveClients,
|
ActiveClients,
|
||||||
|
Log,
|
||||||
OwnClientId,
|
OwnClientId,
|
||||||
StartedParsingStdinQuery,
|
StartedParsingStdinQuery,
|
||||||
DoneParsingStdinQuery,
|
DoneParsingStdinQuery,
|
||||||
|
|
@ -385,6 +387,7 @@ pub enum ServerContext {
|
||||||
AttachClient,
|
AttachClient,
|
||||||
ConnStatus,
|
ConnStatus,
|
||||||
ActiveClients,
|
ActiveClients,
|
||||||
|
Log,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
|
||||||
|
|
|
||||||
|
|
@ -223,6 +223,8 @@ pub enum Action {
|
||||||
ToggleMouseMode,
|
ToggleMouseMode,
|
||||||
PreviousSwapLayout,
|
PreviousSwapLayout,
|
||||||
NextSwapLayout,
|
NextSwapLayout,
|
||||||
|
/// Query all tab names
|
||||||
|
QueryTabNames,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Action {
|
impl Action {
|
||||||
|
|
@ -456,6 +458,7 @@ impl Action {
|
||||||
},
|
},
|
||||||
CliAction::PreviousSwapLayout => Ok(vec![Action::PreviousSwapLayout]),
|
CliAction::PreviousSwapLayout => Ok(vec![Action::PreviousSwapLayout]),
|
||||||
CliAction::NextSwapLayout => Ok(vec![Action::NextSwapLayout]),
|
CliAction::NextSwapLayout => Ok(vec![Action::NextSwapLayout]),
|
||||||
|
CliAction::QueryTabNames => Ok(vec![Action::QueryTabNames]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1943,6 +1943,7 @@ fn cannot_define_stacked_panes_with_grandchildren_in_pane_template() {
|
||||||
assert!(layout.is_err(), "error provided for tab name with space");
|
assert!(layout.is_err(), "error provided for tab name with space");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
fn run_plugin_location_parsing() {
|
fn run_plugin_location_parsing() {
|
||||||
let kdl_layout = r#"
|
let kdl_layout = r#"
|
||||||
layout {
|
layout {
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,7 @@ pub enum ServerToClientMsg {
|
||||||
SwitchToMode(InputMode),
|
SwitchToMode(InputMode),
|
||||||
Connected,
|
Connected,
|
||||||
ActiveClients(Vec<ClientId>),
|
ActiveClients(Vec<ClientId>),
|
||||||
|
Log(Vec<String>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue