aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKen Matsui <26405363+ken-matsui@users.noreply.github.com>2021-11-01 03:14:12 +0900
committerKen Matsui <26405363+ken-matsui@users.noreply.github.com>2021-11-06 05:15:09 +0900
commit4acb2458d2e0da1d0459114f45123841e2fca741 (patch)
tree50a81760d29440580eabdb5e4f691db038e4bb8d /src
parentdocs(changelog): fix link (diff)
downloadsl0ppij-4acb2458d2e0da1d0459114f45123841e2fca741.tar.gz
sl0ppij-4acb2458d2e0da1d0459114f45123841e2fca741.tar.xz
sl0ppij-4acb2458d2e0da1d0459114f45123841e2fca741.zip
feat(attach): Support `--index` option to choose specific session by provided number in active sessions ordered by creation date, resolve #823
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
Diffstat (limited to 'src')
-rw-r--r--src/main.rs119
-rw-r--r--src/sessions.rs53
2 files changed, 132 insertions, 40 deletions
diff --git a/src/main.rs b/src/main.rs
index 0cacc375..f12eb010 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -5,8 +5,9 @@ mod tests;
use crate::install::populate_data_dir;
use sessions::{
- assert_session, assert_session_ne, get_active_session, get_sessions, kill_session,
- list_sessions, print_sessions, session_exists, ActiveSession,
+ 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};
@@ -62,7 +63,7 @@ pub fn main() {
}
}
Err(e) => {
- eprintln!("Error occured: {:?}", e);
+ eprintln!("Error occurred: {:?}", e);
process::exit(1);
}
}
@@ -111,6 +112,7 @@ pub fn main() {
if let Some(Command::Sessions(Sessions::Attach {
session_name,
create,
+ index,
options,
})) = opts.command.clone()
{
@@ -119,47 +121,94 @@ pub fn main() {
None => config_options,
};
- let (client, attach_layout) = match session_name.as_ref() {
- Some(session) => {
- if create {
- if !session_exists(session).unwrap() {
- (ClientInfo::New(session_name.unwrap()), layout)
+ 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 {
- (
- ClientInfo::Attach(session_name.unwrap(), config_options.clone()),
- None,
- )
+ 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);
+ }
+ }
+ }
}
- } else {
- assert_session(session);
- (
- ClientInfo::Attach(session_name.unwrap(), config_options.clone()),
- None,
- )
+ }
+ Err(e) => {
+ eprintln!("Error occurred: {:?}", e);
+ process::exit(1);
}
}
- None => match get_active_session() {
- ActiveSession::None => {
+ } 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::New(names::Generator::default().next().unwrap()),
- layout,
+ ClientInfo::Attach(session_name.unwrap(), config_options.clone()),
+ None,
)
- } 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);
- }
- },
+ 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(
diff --git a/src/sessions.rs b/src/sessions.rs
index c2d8afea..bf44d088 100644
--- a/src/sessions.rs
+++ b/src/sessions.rs
@@ -1,4 +1,5 @@
use std::os::unix::fs::FileTypeExt;
+use std::time::SystemTime;
use std::{fs, io, process};
use zellij_utils::{
consts::ZELLIJ_SOCK_DIR,
@@ -29,6 +30,36 @@ pub(crate) fn get_sessions() -> Result<Vec<String>, io::ErrorKind> {
}
}
+pub(crate) fn get_sessions_sorted_by_creation_date() -> anyhow::Result<Vec<String>> {
+ match fs::read_dir(&*ZELLIJ_SOCK_DIR) {
+ Ok(files) => {
+ let mut sessions_with_creation_date: Vec<(String, SystemTime)> = Vec::new();
+ for file in files {
+ let file = file?;
+ let file_name = file.file_name().into_string().unwrap();
+ let file_created_at = file.metadata()?.created()?;
+ if file.file_type()?.is_socket() && assert_socket(&file_name) {
+ sessions_with_creation_date.push((file_name, file_created_at));
+ }
+ }
+ sessions_with_creation_date.sort_by_key(|x| x.1); // the oldest one will be the first
+
+ let sessions = sessions_with_creation_date
+ .iter()
+ .map(|x| x.0.clone())
+ .collect();
+ Ok(sessions)
+ }
+ Err(err) => {
+ if let io::ErrorKind::NotFound = err.kind() {
+ Ok(Vec::with_capacity(0))
+ } else {
+ Err(err.into())
+ }
+ }
+ }
+}
+
fn assert_socket(name: &str) -> bool {
let path = &*ZELLIJ_SOCK_DIR.join(name);
match LocalSocketStream::connect(path) {
@@ -59,6 +90,18 @@ pub(crate) fn print_sessions(sessions: Vec<String>) {
})
}
+pub(crate) fn print_sessions_with_index(sessions: Vec<String>) {
+ let curr_session = std::env::var("ZELLIJ_SESSION_NAME").unwrap_or_else(|_| "".into());
+ for (i, session) in sessions.iter().enumerate() {
+ let suffix = if curr_session == *session {
+ " (current)"
+ } else {
+ ""
+ };
+ println!("{}: {}{}", i, session, suffix);
+ }
+}
+
pub(crate) enum ActiveSession {
None,
One(String),
@@ -78,7 +121,7 @@ pub(crate) fn get_active_session() -> ActiveSession {
}
}
Err(e) => {
- eprintln!("Error occured: {:?}", e);
+ eprintln!("Error occurred: {:?}", e);
process::exit(1);
}
}
@@ -91,7 +134,7 @@ pub(crate) fn kill_session(name: &str) {
IpcSenderWithContext::new(stream).send(ClientToServerMsg::KillSession);
}
Err(e) => {
- eprintln!("Error occured: {:?}", e);
+ eprintln!("Error occurred: {:?}", e);
process::exit(1);
}
};
@@ -108,7 +151,7 @@ pub(crate) fn list_sessions() {
0
}
Err(e) => {
- eprintln!("Error occured: {:?}", e);
+ eprintln!("Error occurred: {:?}", e);
1
}
};
@@ -137,7 +180,7 @@ pub(crate) fn assert_session(name: &str) {
}
}
Err(e) => {
- eprintln!("Error occured: {:?}", e);
+ eprintln!("Error occurred: {:?}", e);
}
};
process::exit(1);
@@ -151,7 +194,7 @@ pub(crate) fn assert_session_ne(name: &str) {
}
println!("Session with name {:?} aleady exists. Use attach command to connect to it or specify a different name.", name);
}
- Err(e) => eprintln!("Error occured: {:?}", e),
+ Err(e) => eprintln!("Error occurred: {:?}", e),
};
process::exit(1);
}