feat(attach): Support `--first` option for `attach` sub-command to let zellij choose the alphabetically first session; resolve #823 fix(attach-first): Fix `--first` option to choose the first created session in the existent sessions feat(attach): Support `--index` option to choose the session indexed by provided number like -t option of tmux feat(attach): Support listing active sessions with index when a provided number is not found in the active sessions feat(attach): Support listing active sessions with index when a provided number is not found in the active sessions feat: Add anyhow to uniformly treat error types and avoid panics
244 lines
9.1 KiB
Rust
244 lines
9.1 KiB
Rust
mod install;
|
|
mod sessions;
|
|
#[cfg(test)]
|
|
mod tests;
|
|
|
|
use crate::install::populate_data_dir;
|
|
use sessions::{
|
|
assert_session, assert_session_ne, get_active_session, get_sessions,
|
|
get_sessions_sorted_by_creation_date, kill_session, list_sessions, print_sessions,
|
|
print_sessions_with_index, session_exists, ActiveSession,
|
|
};
|
|
use std::process;
|
|
use zellij_client::{os_input_output::get_client_os_input, start_client, ClientInfo};
|
|
use zellij_server::{os_input_output::get_server_os_input, start_server};
|
|
use zellij_utils::{
|
|
cli::{CliArgs, Command, SessionCommand, Sessions},
|
|
logging::*,
|
|
setup::{get_default_data_dir, Setup},
|
|
structopt::StructOpt,
|
|
};
|
|
|
|
pub fn main() {
|
|
configure_logger();
|
|
let opts = CliArgs::from_args();
|
|
|
|
if let Some(Command::Sessions(Sessions::ListSessions)) = opts.command {
|
|
list_sessions();
|
|
}
|
|
|
|
if let Some(Command::Sessions(Sessions::KillAllSessions { yes })) = opts.command {
|
|
match get_sessions() {
|
|
Ok(sessions) => {
|
|
if sessions.is_empty() {
|
|
println!("No active zellij sessions found.");
|
|
process::exit(1);
|
|
} else {
|
|
let kill_all_sessions = |sessions: Vec<std::string::String>| {
|
|
for session in sessions.iter() {
|
|
kill_session(session);
|
|
}
|
|
process::exit(0)
|
|
};
|
|
|
|
if yes {
|
|
kill_all_sessions(sessions);
|
|
} else {
|
|
use std::io::{stdin, stdout, Write};
|
|
|
|
let mut answer = String::new();
|
|
println!("WARNING: this action will kill all sessions.");
|
|
print!("Do you want to continue? [y/N] ");
|
|
let _ = stdout().flush();
|
|
stdin().read_line(&mut answer).unwrap();
|
|
|
|
match answer.as_str().trim() {
|
|
"y" | "Y" | "yes" | "Yes" => kill_all_sessions(sessions),
|
|
_ => {
|
|
println!("Abort.");
|
|
process::exit(1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Err(e) => {
|
|
eprintln!("Error occurred: {:?}", e);
|
|
process::exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
if let Some(Command::Sessions(Sessions::KillSession { target_session })) = opts.command.clone()
|
|
{
|
|
match target_session.as_ref() {
|
|
Some(target_session) => {
|
|
assert_session(target_session);
|
|
kill_session(target_session);
|
|
process::exit(0);
|
|
}
|
|
None => {
|
|
println!("Please specify the session name to kill.");
|
|
process::exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
if let Some(path) = opts.server {
|
|
let os_input = match get_server_os_input() {
|
|
Ok(server_os_input) => server_os_input,
|
|
Err(e) => {
|
|
eprintln!("failed to open terminal:\n{}", e);
|
|
process::exit(1);
|
|
}
|
|
};
|
|
start_server(Box::new(os_input), path);
|
|
} else {
|
|
let (config, layout, config_options) = match Setup::from_options(&opts) {
|
|
Ok(results) => results,
|
|
Err(e) => {
|
|
eprintln!("{}", e);
|
|
process::exit(1);
|
|
}
|
|
};
|
|
|
|
let os_input = match get_client_os_input() {
|
|
Ok(os_input) => os_input,
|
|
Err(e) => {
|
|
eprintln!("failed to open terminal:\n{}", e);
|
|
process::exit(1);
|
|
}
|
|
};
|
|
if let Some(Command::Sessions(Sessions::Attach {
|
|
session_name,
|
|
create,
|
|
index,
|
|
options,
|
|
})) = opts.command.clone()
|
|
{
|
|
let config_options = match options {
|
|
Some(SessionCommand::Options(o)) => config_options.merge(o),
|
|
None => config_options,
|
|
};
|
|
|
|
let (client, attach_layout) = if let Some(idx) = index {
|
|
// Ignore session_name when `--index` is provided
|
|
match get_sessions_sorted_by_creation_date() {
|
|
Ok(sessions) => {
|
|
if sessions.is_empty() {
|
|
if create {
|
|
(
|
|
ClientInfo::New(names::Generator::default().next().unwrap()),
|
|
layout,
|
|
)
|
|
} else {
|
|
println!("No active zellij sessions found.");
|
|
process::exit(1);
|
|
}
|
|
} else {
|
|
match sessions.get(idx) {
|
|
Some(session) => (
|
|
ClientInfo::Attach(session.clone(), config_options.clone()),
|
|
None,
|
|
),
|
|
None => {
|
|
if create {
|
|
(
|
|
ClientInfo::New(
|
|
names::Generator::default().next().unwrap(),
|
|
),
|
|
layout,
|
|
)
|
|
} else {
|
|
println!("No session indexed by {} found. The following sessions are active:", idx);
|
|
print_sessions_with_index(sessions);
|
|
process::exit(1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Err(e) => {
|
|
eprintln!("Error occurred: {:?}", e);
|
|
process::exit(1);
|
|
}
|
|
}
|
|
} else {
|
|
match session_name.as_ref() {
|
|
Some(session) => {
|
|
if create {
|
|
if !session_exists(session).unwrap() {
|
|
(ClientInfo::New(session_name.unwrap()), layout)
|
|
} else {
|
|
(
|
|
ClientInfo::Attach(
|
|
session_name.unwrap(),
|
|
config_options.clone(),
|
|
),
|
|
None,
|
|
)
|
|
}
|
|
} else {
|
|
assert_session(session);
|
|
(
|
|
ClientInfo::Attach(session_name.unwrap(), config_options.clone()),
|
|
None,
|
|
)
|
|
}
|
|
}
|
|
None => match get_active_session() {
|
|
ActiveSession::None => {
|
|
if create {
|
|
(
|
|
ClientInfo::New(names::Generator::default().next().unwrap()),
|
|
layout,
|
|
)
|
|
} else {
|
|
println!("No active zellij sessions found.");
|
|
process::exit(1);
|
|
}
|
|
}
|
|
ActiveSession::One(session_name) => (
|
|
ClientInfo::Attach(session_name, config_options.clone()),
|
|
None,
|
|
),
|
|
ActiveSession::Many => {
|
|
println!("Please specify the session name to attach to. The following sessions are active:");
|
|
print_sessions(get_sessions().unwrap());
|
|
process::exit(1);
|
|
}
|
|
},
|
|
}
|
|
};
|
|
|
|
start_client(
|
|
Box::new(os_input),
|
|
opts,
|
|
config,
|
|
config_options,
|
|
client,
|
|
attach_layout,
|
|
);
|
|
} else {
|
|
let session_name = opts
|
|
.session
|
|
.clone()
|
|
.unwrap_or_else(|| names::Generator::default().next().unwrap());
|
|
assert_session_ne(&session_name);
|
|
|
|
// Determine and initialize the data directory
|
|
let data_dir = opts.data_dir.clone().unwrap_or_else(get_default_data_dir);
|
|
#[cfg(not(disable_automatic_asset_installation))]
|
|
populate_data_dir(&data_dir);
|
|
|
|
start_client(
|
|
Box::new(os_input),
|
|
opts,
|
|
config,
|
|
config_options,
|
|
ClientInfo::New(session_name),
|
|
layout,
|
|
);
|
|
}
|
|
}
|
|
}
|