1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
use std::os::unix::fs::FileTypeExt;
use std::time::SystemTime;
use std::{fs, io, process};
use zellij_utils::{
consts::ZELLIJ_SOCK_DIR,
interprocess::local_socket::LocalSocketStream,
ipc::{ClientToServerMsg, IpcSenderWithContext},
};
pub(crate) fn get_sessions() -> Result<Vec<String>, io::ErrorKind> {
match fs::read_dir(&*ZELLIJ_SOCK_DIR) {
Ok(files) => {
let mut sessions = Vec::new();
files.for_each(|file| {
let file = file.unwrap();
let file_name = file.file_name().into_string().unwrap();
if file.file_type().unwrap().is_socket() && assert_socket(&file_name) {
sessions.push(file_name);
}
});
Ok(sessions)
}
Err(err) if io::ErrorKind::NotFound != err.kind() => Err(err.kind()),
Err(_) => Ok(Vec::with_capacity(0)),
}
}
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 io::ErrorKind::NotFound != err.kind() => Err(err.into()),
Err(_) => Ok(Vec::with_capacity(0)),
}
}
fn assert_socket(name: &str) -> bool {
let path = &*ZELLIJ_SOCK_DIR.join(name);
match LocalSocketStream::connect(path) {
Ok(stream) => {
IpcSenderWithContext::new(stream).send(ClientToServerMsg::ClientExited);
true
}
Err(e) if e.kind() == io::ErrorKind::ConnectionRefused => {
drop(fs::remove_file(path));
false
}
Err(_) => true,
}
}
pub(crate) fn print_sessions(sessions: Vec<String>) {
let curr_session = std::env::var("ZELLIJ_SESSION_NAME").unwrap_or_else(|_| "".into());
sessions.iter().for_each(|session| {
let suffix = if curr_session == *session {
" (current)"
} else {
""
};
println!("{}{}", session, suffix);
})
}
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),
Many,
}
pub(crate) fn get_active_session() -> ActiveSession {
match get_sessions() {
Ok(sessions) if sessions.is_empty() => ActiveSession::None,
Ok(mut sessions) if sessions.len() == 1 => ActiveSession::One(sessions.pop().unwrap()),
Ok(_) => ActiveSession::Many,
Err(e) => {
eprintln!("Error occurred: {:?}", e);
process::exit(1);
}
}
}
pub(crate) fn kill_session(name: &str) {
let path = &*ZELLIJ_SOCK_DIR.join(name);
match LocalSocketStream::connect(path) {
Ok(stream) => {
IpcSenderWithContext::new(stream).send(ClientToServerMsg::KillSession);
}
Err(e) => {
eprintln!("Error occurred: {:?}", e);
process::exit(1);
}
};
}
pub(crate) fn list_sessions() {
let exit_code = match get_sessions() {
Ok(sessions) if !sessions.is_empty() => {
print_sessions(sessions);
0
}
Ok(_) => {
println!("No active zellij sessions found.");
0
}
Err(e) => {
eprintln!("Error occurred: {:?}", e);
1
}
};
process::exit(exit_code);
}
pub(crate) fn session_exists(name: &str) -> Result<bool, io::ErrorKind> {
return match get_sessions() {
Ok(sessions) if sessions.iter().any(|s| s == name) => Ok(true),
Ok(_) => Ok(false),
Err(e) => Err(e),
};
}
pub(crate) fn assert_session(name: &str) {
match session_exists(name) {
Ok(result) if result => return,
Ok(_) => println!("No session named {:?} found.", name),
Err(e) => eprintln!("Error occurred: {:?}", e),
};
process::exit(1);
}
pub(crate) fn assert_session_ne(name: &str) {
match session_exists(name) {
Ok(result) if !result => return,
Ok(_) => println!("Session with name {:?} already exists. Use attach command to connect to it or specify a different name.", name),
Err(e) => eprintln!("Error occurred: {:?}", e),
};
process::exit(1);
}
|