Skip to content

Commit c92c50b

Browse files
dbachelderclaude
andcommitted
fix(resurrectable): fix delete and sort by age
- Check if session is resurrectable BEFORE optimistic removal (was removing from list then checking, so delete always failed) - Sort resurrectable sessions by duration ascending (most recent first) - Remove unused SessionAction::Kill variant Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 2b7c2ae commit c92c50b

File tree

5 files changed

+38
-25
lines changed

5 files changed

+38
-25
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
/target
22
/ref
3+
deploy.sh

deploy.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ fi
1919

2020
echo "Deploying to $REMOTE"
2121
scp "$WASM" "$REMOTE"
22+
cp -f "$WASM" ~/.config/zellij/plugins/
2223

2324
echo "Done. Reload plugin in zellij with Alt+R or:"
2425
echo " zellij action start-or-reload-plugin file:~/.config/zellij/plugins/zsm.wasm"

src/session/manager.rs

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -130,19 +130,6 @@ impl SessionManager {
130130
SessionAction::Switch(name) => {
131131
switch_session(Some(&name));
132132
}
133-
SessionAction::Kill(name) => {
134-
if self
135-
.resurrectable_sessions
136-
.iter()
137-
.any(|(session_name, _)| session_name == &name)
138-
{
139-
// If the session is resurrectable, we should delete it
140-
delete_dead_session(&name);
141-
} else {
142-
// Otherwise, we need to kill the session
143-
kill_sessions(&[&name]);
144-
}
145-
}
146133
}
147134
}
148135

@@ -197,13 +184,24 @@ impl SessionManager {
197184
/// Uses optimistic update - removes from local state immediately before sending kill command
198185
pub fn confirm_deletion(&mut self) {
199186
if let Some(session_name) = self.pending_deletion.take() {
187+
// Check if it's a resurrectable session BEFORE the optimistic removal
188+
// (removal clears the list, so we must check first)
189+
let is_resurrectable = self
190+
.resurrectable_sessions
191+
.iter()
192+
.any(|(name, _)| name == &session_name);
193+
200194
// Optimistic update: Remove session from local state immediately
201195
// This provides instant UI feedback rather than waiting for MISSING_THRESHOLD updates
202196
self.remove_session_from_local_state(&session_name);
203197

204198
// Now execute the actual kill/delete action
205199
// If this fails, the session will reappear on the next SessionUpdate event
206-
self.execute_action(SessionAction::Kill(session_name));
200+
if is_resurrectable {
201+
delete_dead_session(&session_name);
202+
} else {
203+
kill_sessions(&[&session_name]);
204+
}
207205
}
208206
}
209207

src/session/types.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,4 @@ impl SessionItem {
4040
pub enum SessionAction {
4141
/// Switch to an existing session
4242
Switch(String),
43-
/// Kill an existing session
44-
Kill(String),
4543
}

src/state.rs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -156,22 +156,23 @@ impl PluginState {
156156

157157
/// Combine sessions and zoxide directories for display
158158
fn combined_items(&self) -> Vec<SessionItem> {
159-
let mut sessions: Vec<SessionItem> = Vec::new();
159+
let mut existing_sessions: Vec<SessionItem> = Vec::new();
160+
let mut resurrectable_sessions: Vec<SessionItem> = Vec::new();
160161
let mut directories: Vec<SessionItem> = Vec::new();
161162
let mut added_session_names = HashSet::new();
162163

163164
// First, collect existing sessions that match zoxide directories (including incremented ones)
164165
for session in self.session_manager.sessions() {
165166
if let Some(zoxide_dir) = self.find_matching_zoxide_dir(&session.name) {
166-
sessions.push(SessionItem::ExistingSession {
167+
existing_sessions.push(SessionItem::ExistingSession {
167168
name: session.name.clone(),
168169
directory: zoxide_dir.directory.clone(),
169170
is_current: session.is_current_session,
170171
});
171172
added_session_names.insert(session.name.clone());
172173
} else if self.config.show_all_sessions {
173174
// Session didn't match any zoxide dir, but show_all_sessions is enabled
174-
sessions.push(SessionItem::ExistingSession {
175+
existing_sessions.push(SessionItem::ExistingSession {
175176
name: session.name.clone(),
176177
directory: String::new(),
177178
is_current: session.is_current_session,
@@ -190,7 +191,7 @@ impl PluginState {
190191

191192
let matches_zoxide = self.find_matching_zoxide_dir(name).is_some();
192193
if matches_zoxide || self.config.show_all_sessions {
193-
sessions.push(SessionItem::ResurrectableSession {
194+
resurrectable_sessions.push(SessionItem::ResurrectableSession {
194195
name: name.clone(),
195196
duration: *duration,
196197
});
@@ -206,24 +207,38 @@ impl PluginState {
206207
});
207208
}
208209

209-
// Sort sessions based on config
210+
// Sort existing sessions based on config
210211
match self.config.sort_order {
211212
SortOrder::Mru => {
212213
// Sort by MRU timestamp (descending - most recent first)
213-
sessions.sort_by(|a, b| {
214+
existing_sessions.sort_by(|a, b| {
214215
let ts_a = self.session_manager.get_mru_rank(a.name());
215216
let ts_b = self.session_manager.get_mru_rank(b.name());
216217
ts_b.cmp(&ts_a) // Descending order
217218
});
218219
}
219220
SortOrder::Alphabetical => {
220221
// Sort alphabetically by name (case-insensitive)
221-
sessions.sort_by_key(|a| a.name().to_lowercase());
222+
existing_sessions.sort_by_key(|a| a.name().to_lowercase());
222223
}
223224
}
224225

225-
// Combine: sorted sessions first, then directories (already sorted by zoxide score)
226-
let mut items = sessions;
226+
// Sort resurrectable sessions by age (most recently killed first = smallest duration)
227+
resurrectable_sessions.sort_by(|a, b| {
228+
let dur_a = match a {
229+
SessionItem::ResurrectableSession { duration, .. } => *duration,
230+
_ => std::time::Duration::MAX,
231+
};
232+
let dur_b = match b {
233+
SessionItem::ResurrectableSession { duration, .. } => *duration,
234+
_ => std::time::Duration::MAX,
235+
};
236+
dur_a.cmp(&dur_b) // Ascending order (smallest/most recent first)
237+
});
238+
239+
// Combine: existing sessions, then resurrectable, then directories
240+
let mut items = existing_sessions;
241+
items.append(&mut resurrectable_sessions);
227242
items.append(&mut directories);
228243
items
229244
}

0 commit comments

Comments
 (0)