Function bodies 251 total
new function · rust · L90-L116 (27 LOC)src/app.rs
pub fn new(sessions: Vec<Session>, trash: Vec<Session>) -> Self {
Self {
current_tab: Tab::Sessions,
sessions,
trash,
selected_session_idx: 0,
preview_scroll: 0,
search_query: String::new(),
show_search: false,
status_message: None,
status_message_time: None,
confirm_action: None,
resume_session_id: None,
resume_session_path: None,
focus: FocusPanel::List,
sort_field: SortField::Date,
sort_direction: SortDirection::Descending,
show_help: false,
help_scroll: 0,
show_settings: false,
settings_input: String::new(),
config: AppConfig::load(),
list_table_state: TableState::default(),
terminal_size: (0, 0),
click_regions: Vec::new(),
}
}with_sessions function · rust · L119-L145 (27 LOC)src/app.rs
pub fn with_sessions(sessions: Vec<Session>) -> Self {
Self {
current_tab: Tab::Sessions,
sessions,
trash: Vec::new(),
selected_session_idx: 0,
preview_scroll: 0,
search_query: String::new(),
show_search: false,
status_message: None,
status_message_time: None,
confirm_action: None,
resume_session_id: None,
resume_session_path: None,
focus: FocusPanel::List,
sort_field: SortField::Date,
sort_direction: SortDirection::Descending,
show_help: false,
help_scroll: 0,
show_settings: false,
settings_input: String::new(),
config: AppConfig::default(),
list_table_state: TableState::default(),
terminal_size: (0, 0),
click_regions: Vec::new(),
}
}select_next function · rust · L146-L153 (8 LOC)src/app.rs
pub fn select_next(&mut self) {
let list = self.filtered_sessions();
if !list.is_empty() && self.selected_session_idx < list.len() - 1 {
self.selected_session_idx += 1;
self.preview_scroll = 0;
}
}select_prev function · rust · L154-L160 (7 LOC)src/app.rs
pub fn select_prev(&mut self) {
if self.selected_session_idx > 0 {
self.selected_session_idx -= 1;
self.preview_scroll = 0;
}
}switch_tab function · rust · L161-L169 (9 LOC)src/app.rs
pub fn switch_tab(&mut self) {
self.current_tab = match self.current_tab {
Tab::Sessions => Tab::Trash,
Tab::Trash => Tab::Sessions,
};
self.selected_session_idx = 0;
self.preview_scroll = 0;
}switch_to_tab function · rust · L170-L175 (6 LOC)src/app.rs
pub fn switch_to_tab(&mut self, tab: Tab) {
self.current_tab = tab;
self.selected_session_idx = 0;
self.preview_scroll = 0;
}get_click_action function · rust · L178-L186 (9 LOC)src/app.rs
pub fn get_click_action(&self, col: u16, row: u16) -> Option<ClickAction> {
let pos = Position { x: col, y: row };
for (rect, action) in &self.click_regions {
if rect.contains(pos) {
return Some(action.clone());
}
}
None
}Want this analysis on your repo? https://repobility.com/scan/
handle_list_click function · rust · L190-L214 (25 LOC)src/app.rs
pub fn handle_list_click(&mut self, col: u16, row: u16) {
let (width, height) = self.terminal_size;
if width == 0 || height == 0 {
return;
}
// Tab-Bar und Command-Bar überspringen
if row < 3 || row >= height.saturating_sub(3) {
return;
}
let list_width = width * 30 / 100;
if col < list_width {
// Zeile 3=Border, 4=Header, 5+=Session-Einträge
if row >= 5 {
let clicked = self.list_table_state.offset() + (row - 5) as usize;
let len = self.filtered_sessions().len();
if clicked < len {
self.selected_session_idx = clicked;
self.preview_scroll = 0;
self.focus = FocusPanel::List;
}
}
} else {
self.focus = FocusPanel::Preview;
}
}current_list function · rust · L220-L226 (7 LOC)src/app.rs
pub fn current_list(&self) -> &Vec<Session> {
match self.current_tab {
Tab::Sessions => &self.sessions,
Tab::Trash => &self.trash,
}
}page_down function · rust · L235-L250 (16 LOC)src/app.rs
pub fn page_down(&mut self, page_size: usize) {
match self.focus {
FocusPanel::List => {
let list = self.filtered_sessions();
if !list.is_empty() {
self.selected_session_idx =
(self.selected_session_idx + page_size).min(list.len() - 1);
self.preview_scroll = 0;
}
}
FocusPanel::Preview => {
self.preview_scroll = self.preview_scroll.saturating_add(page_size as u16);
}
}
}page_up function · rust · L251-L262 (12 LOC)src/app.rs
pub fn page_up(&mut self, page_size: usize) {
match self.focus {
FocusPanel::List => {
self.selected_session_idx = self.selected_session_idx.saturating_sub(page_size);
self.preview_scroll = 0;
}
FocusPanel::Preview => {
self.preview_scroll = self.preview_scroll.saturating_sub(page_size as u16);
}
}
}filtered_sessions function · rust · L271-L304 (34 LOC)src/app.rs
pub fn filtered_sessions(&self) -> Vec<&Session> {
let list = self.current_list();
let mut filtered: Vec<&Session> = if self.search_query.is_empty() {
list.iter().collect()
} else {
let q = self.search_query.to_lowercase();
list.iter()
.filter(|s| {
s.id.to_lowercase().contains(&q)
|| s.project_name.to_lowercase().contains(&q)
|| s.messages
.iter()
.any(|m| m.content.to_lowercase().contains(&q))
})
.collect()
};
filtered.sort_by(|a, b| {
let ordering = match self.sort_field {
SortField::Project => a.project_name.cmp(&b.project_name),
SortField::Messages => a.messages.len().cmp(&b.messages.len()),
SortField::Date => a.updated_at.cmp(&b.updated_at),
};
mtoggle_sort function · rust · L305-L313 (9 LOC)src/app.rs
pub fn toggle_sort(&mut self) {
self.sort_field = match self.sort_field {
SortField::Project => SortField::Messages,
SortField::Messages => SortField::Date,
SortField::Date => SortField::Project,
};
self.sort_direction = SortDirection::Descending;
}toggle_sort_direction function · rust · L314-L320 (7 LOC)src/app.rs
pub fn toggle_sort_direction(&mut self) {
self.sort_direction = match self.sort_direction {
SortDirection::Ascending => SortDirection::Descending,
SortDirection::Descending => SortDirection::Ascending,
};
}toggle_help function · rust · L321-L327 (7 LOC)src/app.rs
pub fn toggle_help(&mut self) {
self.show_help = !self.show_help;
if !self.show_help {
self.help_scroll = 0;
}
}About: code-quality intelligence by Repobility · https://repobility.com
toggle_search function · rust · L336-L342 (7 LOC)src/app.rs
pub fn toggle_search(&mut self) {
self.show_search = !self.show_search;
if !self.show_search {
self.search_query.clear();
}
}move_selected_to_trash function · rust · L353-L376 (24 LOC)src/app.rs
pub fn move_selected_to_trash(&mut self) {
if self.current_tab != Tab::Sessions {
return;
}
let filtered = self.filtered_sessions();
if let Some(session) = filtered.get(self.selected_session_idx) {
let id = session.id.clone();
if let Some(pos) = self.sessions.iter().position(|s| s.id == id) {
let removed = self.sessions.remove(pos);
let store = SessionStore::new();
let _ = store.move_to_trash(&removed.project_name, &removed.id);
self.trash.push(removed);
self.set_status(format!("Moved to trash: {}", id));
if self.selected_session_idx > 0 && self.selected_session_idx >= self.sessions.len()
{
self.selected_session_idx -= 1;
}
}
}
}restore_selected_from_trash function · rust · L377-L400 (24 LOC)src/app.rs
pub fn restore_selected_from_trash(&mut self) {
if self.current_tab != Tab::Trash {
self.set_status("Switch to Trash tab first".to_string());
return;
}
let filtered = self.filtered_sessions();
if let Some(session) = filtered.get(self.selected_session_idx) {
let id = session.id.clone();
if let Some(pos) = self.trash.iter().position(|s| s.id == id) {
let removed = self.trash.remove(pos);
let store = SessionStore::new();
let _ = store.restore_session_file(&removed);
self.sessions.push(removed);
self.set_status(format!("Restored: {}", id));
if self.selected_session_idx > 0 && self.selected_session_idx >= self.trash.len() {
self.selected_session_idx -= 1;
}
}
}
}switch_to_selected_session function · rust · L401-L414 (14 LOC)src/app.rs
pub fn switch_to_selected_session(&mut self) {
if let Some(session) = self.get_selected_session() {
let session_id = session.id.clone();
let project_path = session.project_path.clone();
let project_name = session.project_name.clone();
self.resume_session_id = Some(session_id.clone());
self.resume_session_path = Some(project_path);
self.set_status(format!(
"Resuming session: {} | claude --resume {}",
project_name, session_id
));
}
}get_resume_command function · rust · L415-L420 (6 LOC)src/app.rs
pub fn get_resume_command(&self) -> Option<String> {
self.resume_session_id
.as_ref()
.map(|id| format!("claude --resume {}", id))
}request_delete_confirmation function · rust · L425-L453 (29 LOC)src/app.rs
pub fn request_delete_confirmation(&mut self) {
if let Some(session) = self.get_selected_session() {
let session_id = session.id.clone();
let project_name = session.project_name.clone();
let action = if self.current_tab == Tab::Trash {
ConfirmAction::DeletePermanently(session_id)
} else {
ConfirmAction::DeleteToTrash(session_id)
};
self.confirm_action = Some(action.clone());
let message = match action {
ConfirmAction::DeleteToTrash(_) => format!(
"Move '{}' to trash? Press 'd' or 'y' to confirm, 'n' or Esc to cancel",
project_name
),
ConfirmAction::DeletePermanently(_) => format!(
"PERMANENTLY delete '{}'? Press 'd' or 'y' to confirm, 'n' or Esc to cancel",
project_name
),
_ => String::new(),
request_empty_trash function · rust · L454-L471 (18 LOC)src/app.rs
pub fn request_empty_trash(&mut self) {
if self.current_tab != Tab::Trash {
return;
}
let count = self.trash.len();
if count == 0 {
self.set_status("Trash is already empty".to_string());
return;
}
self.confirm_action = Some(ConfirmAction::EmptyTrash);
self.set_status(format!(
"PERMANENTLY delete ALL {} sessions in trash? Press 't' or 'y' to confirm, 'n' or Esc to cancel",
count
));
}request_trash_zero_messages function · rust · L472-L493 (22 LOC)src/app.rs
pub fn request_trash_zero_messages(&mut self) {
if self.current_tab != Tab::Sessions {
return;
}
let count = self
.sessions
.iter()
.filter(|s| s.messages.is_empty())
.count();
if count == 0 {
self.set_status("No empty sessions found".to_string());
return;
}
self.confirm_action = Some(ConfirmAction::TrashZeroMessages);
self.set_status(format!(
"Move {} session(s) with 0 messages to trash? Press 'y' to confirm, 'n' or Esc to cancel",
count
));
}All rows scored by the Repobility analyzer (https://repobility.com)
trash_zero_messages function · rust · L494-L516 (23 LOC)src/app.rs
pub fn trash_zero_messages(&mut self) {
let (empty, non_empty): (Vec<_>, Vec<_>) =
self.sessions.drain(..).partition(|s| s.messages.is_empty());
let count = empty.len();
self.sessions = non_empty;
let store = SessionStore::new();
for session in &empty {
let _ = store.move_to_trash(&session.project_name, &session.id);
}
self.trash.extend(empty);
if self.selected_session_idx >= self.sessions.len() && !self.sessions.is_empty() {
self.selected_session_idx = self.sessions.len() - 1;
} else if self.sessions.is_empty() {
self.selected_session_idx = 0;
}
self.confirm_action = None;
self.set_status(format!("Moved {} empty session(s) to trash", count));
}confirm_and_execute function · rust · L526-L544 (19 LOC)src/app.rs
pub fn confirm_and_execute(&mut self) {
if let Some(action) = self.confirm_action.clone() {
match action {
ConfirmAction::DeleteToTrash(_) => {
// This is handled in main.rs by calling delete_session + move_to_trash
}
ConfirmAction::DeletePermanently(_) => {
self.delete_permanently();
}
ConfirmAction::EmptyTrash => {
self.empty_trash();
}
ConfirmAction::TrashZeroMessages => {
self.trash_zero_messages();
}
}
}
}delete_permanently function · rust · L545-L563 (19 LOC)src/app.rs
fn delete_permanently(&mut self) {
let session_id = if let Some(ConfirmAction::DeletePermanently(id)) = &self.confirm_action {
id.clone()
} else {
return;
};
if let Some(pos) = self.trash.iter().position(|s| s.id == session_id) {
self.trash.remove(pos);
self.set_status(format!("Permanently deleted: {}", session_id));
self.confirm_action = None;
if self.selected_session_idx > 0 && self.selected_session_idx >= self.trash.len() {
self.selected_session_idx -= 1;
}
}
}empty_trash function · rust · L564-L576 (13 LOC)src/app.rs
fn empty_trash(&mut self) {
let count = self.trash.len();
let store = SessionStore::new();
let _ = store.empty_trash();
self.trash.clear();
self.set_status(format!("Permanently deleted {} sessions", count));
self.confirm_action = None;
self.selected_session_idx = 0;
}save_settings function · rust · L582-L588 (7 LOC)src/app.rs
pub fn save_settings(&mut self) {
self.config.export_path = self.settings_input.clone();
let _ = self.config.save();
self.show_settings = false;
self.set_status(format!("Settings saved: {}", self.settings_input));
}clear_expired_status function · rust · L606-L614 (9 LOC)src/app.rs
pub fn clear_expired_status(&mut self) {
if let Some(time) = self.status_message_time {
if time.elapsed().as_secs() >= 3 {
self.status_message = None;
self.status_message_time = None;
}
}
}make_session function · rust · L621-L636 (16 LOC)src/app.rs
fn make_session(id: &str, project: &str) -> Session {
Session {
id: id.to_string(),
project_path: format!("/home/g/{}", project),
project_name: project.to_string(),
created_at: String::new(),
updated_at: String::new(),
size: 0,
total_entries: 1,
messages: vec![Message {
role: "user".to_string(),
content: format!("msg in {}", id),
}],
}
}test_select_next_and_prev function · rust · L639-L659 (21 LOC)src/app.rs
fn test_select_next_and_prev() {
let mut app = App::with_sessions(vec![
make_session("s1", "proj1"),
make_session("s2", "proj2"),
make_session("s3", "proj3"),
]);
assert_eq!(app.selected_session_idx, 0);
app.select_next();
assert_eq!(app.selected_session_idx, 1);
app.select_next();
assert_eq!(app.selected_session_idx, 2);
app.select_next();
assert_eq!(app.selected_session_idx, 2); // stays at end
app.select_prev();
assert_eq!(app.selected_session_idx, 1);
app.select_prev();
assert_eq!(app.selected_session_idx, 0);
app.select_prev();
assert_eq!(app.selected_session_idx, 0); // stays at start
}Repobility · code-quality intelligence platform · https://repobility.com
test_switch_tab_resets_selection function · rust · L662-L670 (9 LOC)src/app.rs
fn test_switch_tab_resets_selection() {
let mut app = App::with_sessions(vec![make_session("s1", "p1"), make_session("s2", "p2")]);
app.selected_session_idx = 1;
app.switch_tab();
assert_eq!(app.current_tab, Tab::Trash);
assert_eq!(app.selected_session_idx, 0);
app.switch_tab();
assert_eq!(app.current_tab, Tab::Sessions);
}test_search_filters_by_id function · rust · L673-L682 (10 LOC)src/app.rs
fn test_search_filters_by_id() {
let mut app = App::with_sessions(vec![
make_session("auto-service", "proj1"),
make_session("dms-project", "proj2"),
]);
app.search_query = "auto".to_string();
let filtered = app.filtered_sessions();
assert_eq!(filtered.len(), 1);
assert_eq!(filtered[0].id, "auto-service");
}test_search_filters_by_project_name function · rust · L685-L694 (10 LOC)src/app.rs
fn test_search_filters_by_project_name() {
let mut app = App::with_sessions(vec![
make_session("s1", "auto-service"),
make_session("s2", "dms-project"),
]);
app.search_query = "dms".to_string();
let filtered = app.filtered_sessions();
assert_eq!(filtered.len(), 1);
assert_eq!(filtered[0].project_name, "dms-project");
}test_search_filters_by_message_content function · rust · L697-L706 (10 LOC)src/app.rs
fn test_search_filters_by_message_content() {
let mut app = App::with_sessions(vec![
make_session("s1", "proj1"),
make_session("s2", "proj2"),
]);
app.search_query = "msg in s2".to_string();
let filtered = app.filtered_sessions();
assert_eq!(filtered.len(), 1);
assert_eq!(filtered[0].id, "s2");
}test_move_to_trash function · rust · L709-L716 (8 LOC)src/app.rs
fn test_move_to_trash() {
let mut app = App::with_sessions(vec![make_session("s1", "p1"), make_session("s2", "p2")]);
app.selected_session_idx = 0;
app.move_selected_to_trash();
assert_eq!(app.sessions.len(), 1);
assert_eq!(app.trash.len(), 1);
assert_eq!(app.trash[0].id, "s1");
}test_restore_from_trash function · rust · L719-L729 (11 LOC)src/app.rs
fn test_restore_from_trash() {
let mut app = App::with_sessions(vec![make_session("s1", "p1")]);
app.move_selected_to_trash();
assert_eq!(app.sessions.len(), 0);
assert_eq!(app.trash.len(), 1);
app.switch_tab(); // to Trash
app.restore_selected_from_trash();
assert_eq!(app.sessions.len(), 1);
assert_eq!(app.trash.len(), 0);
}test_scroll_preview function · rust · L739-L752 (14 LOC)src/app.rs
fn test_scroll_preview() {
let mut app = App::with_sessions(vec![]);
app.focus = FocusPanel::Preview;
app.page_down(3);
assert_eq!(app.preview_scroll, 3);
app.page_down(3);
assert_eq!(app.preview_scroll, 6);
app.page_up(3);
assert_eq!(app.preview_scroll, 3);
app.page_up(3);
assert_eq!(app.preview_scroll, 0);
app.page_up(3); // no underflow
assert_eq!(app.preview_scroll, 0);
}test_select_next_resets_scroll function · rust · L755-L760 (6 LOC)src/app.rs
fn test_select_next_resets_scroll() {
let mut app = App::with_sessions(vec![make_session("s1", "p1"), make_session("s2", "p2")]);
app.preview_scroll = 10;
app.select_next();
assert_eq!(app.preview_scroll, 0);
}Want this analysis on your repo? https://repobility.com/scan/
test_switch_to_selected_session function · rust · L763-L769 (7 LOC)src/app.rs
fn test_switch_to_selected_session() {
let mut app = App::with_sessions(vec![make_session("abc-123", "myproject")]);
app.switch_to_selected_session();
let msg = app.status_message.unwrap();
assert!(msg.contains("claude --resume abc-123"));
assert!(msg.contains("myproject"));
}test_move_to_trash_adjusts_index function · rust · L772-L777 (6 LOC)src/app.rs
fn test_move_to_trash_adjusts_index() {
let mut app = App::with_sessions(vec![make_session("s1", "p1"), make_session("s2", "p2")]);
app.selected_session_idx = 1;
app.move_selected_to_trash();
assert_eq!(app.selected_session_idx, 0);
}test_set_status_sets_both_message_and_time function · rust · L780-L787 (8 LOC)src/app.rs
fn test_set_status_sets_both_message_and_time() {
let mut app = App::with_sessions(vec![]);
app.set_status("Test message".to_string());
assert!(app.status_message.is_some());
assert!(app.status_message_time.is_some());
assert_eq!(app.status_message.unwrap(), "Test message");
}test_clear_expired_status_removes_after_expiry function · rust · L790-L804 (15 LOC)src/app.rs
fn test_clear_expired_status_removes_after_expiry() {
let mut app = App::with_sessions(vec![]);
app.set_status("Test message".to_string());
// Immediately clear - should not remove (less than 3 seconds)
app.clear_expired_status();
assert!(app.status_message.is_some());
// Manually set time to 3+ seconds ago
use std::time::Instant;
app.status_message_time = Some(Instant::now() - std::time::Duration::from_secs(3));
app.clear_expired_status();
assert!(app.status_message.is_none());
assert!(app.status_message_time.is_none());
}test_export_status_uses_set_status function · rust · L807-L815 (9 LOC)src/app.rs
fn test_export_status_uses_set_status() {
let mut app = App::with_sessions(vec![make_session("test-id", "test-proj")]);
// Simulate export success by manually calling set_status
app.set_status("Exported to /path/file.md".to_string());
assert!(app.status_message.is_some());
assert!(app.status_message_time.is_some());
assert!(app.status_message.unwrap().contains("Exported to"));
}test_request_delete_confirmation_uses_set_status function · rust · L818-L826 (9 LOC)src/app.rs
fn test_request_delete_confirmation_uses_set_status() {
let mut app = App::with_sessions(vec![make_session("s1", "p1")]);
app.request_delete_confirmation();
// Status message should be set with time
assert!(app.status_message.is_some());
assert!(app.status_message_time.is_some());
assert!(app.status_message.unwrap().contains("trash"));
}test_request_empty_trash_uses_set_status function · rust · L829-L839 (11 LOC)src/app.rs
fn test_request_empty_trash_uses_set_status() {
let mut app = App::with_sessions(vec![]);
app.trash = vec![make_session("s1", "p1")];
app.current_tab = Tab::Trash;
app.request_empty_trash();
// Status message should be set with time
assert!(app.status_message.is_some());
assert!(app.status_message_time.is_some());
assert!(app.status_message.unwrap().contains("PERMANENTLY delete"));
}test_trash_zero_messages_moves_empty_sessions function · rust · L842-L853 (12 LOC)src/app.rs
fn test_trash_zero_messages_moves_empty_sessions() {
let mut app = App::with_sessions(vec![make_session("s1", "p1"), make_session("s2", "p2")]);
// Make s2 have 0 messages
app.sessions[1].messages.clear();
app.trash_zero_messages();
assert_eq!(app.sessions.len(), 1);
assert_eq!(app.sessions[0].id, "s1");
assert_eq!(app.trash.len(), 1);
assert_eq!(app.trash[0].id, "s2");
}About: code-quality intelligence by Repobility · https://repobility.com
test_trash_zero_messages_moves_all_empty function · rust · L856-L870 (15 LOC)src/app.rs
fn test_trash_zero_messages_moves_all_empty() {
let mut app = App::with_sessions(vec![
make_session("s1", "p1"),
make_session("s2", "p2"),
make_session("s3", "p3"),
]);
app.sessions[0].messages.clear();
app.sessions[2].messages.clear();
app.trash_zero_messages();
assert_eq!(app.sessions.len(), 1);
assert_eq!(app.sessions[0].id, "s2");
assert_eq!(app.trash.len(), 2);
}test_trash_zero_messages_none_empty function · rust · L873-L880 (8 LOC)src/app.rs
fn test_trash_zero_messages_none_empty() {
let mut app = App::with_sessions(vec![make_session("s1", "p1")]);
app.trash_zero_messages();
assert_eq!(app.sessions.len(), 1);
assert_eq!(app.trash.len(), 0);
}test_trash_zero_messages_adjusts_selection function · rust · L883-L897 (15 LOC)src/app.rs
fn test_trash_zero_messages_adjusts_selection() {
let mut app = App::with_sessions(vec![
make_session("s1", "p1"),
make_session("s2", "p2"),
make_session("s3", "p3"),
]);
app.sessions[0].messages.clear();
app.sessions[1].messages.clear();
app.selected_session_idx = 2;
app.trash_zero_messages();
// Only s3 remains, selection should be 0
assert_eq!(app.selected_session_idx, 0);
}page 1 / 6next ›