Repository: atuinsh/atuin (language: rust)

Issue:
atuin crashes on "Inspect" with empty history
This edge case could probably be handled more elegantly so that `atuin` doesn't crash with a cryptic error message.

# Steps to reproduce

1. `TMPDIR=$(mktemp -dp.) && cd $TMPDIR`
2. `^R` to start `atuin`
3. Toggle "Directory" mode
   - NOTE: Because we're in a new directory, "Directory" mode will show no entries.
5. `^O` to enter the "Inspect" panel

`atuin` should crash with the following error:

```
thread 'main' panicked at atuin/src/command/client/search/interactive.rs:970:35:
index out of bounds: the len is 0 but the index is 0
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```

# Environment

macOS 14.3.1 (23D60)

```
❯ atuin --version
atuin 18.0.1
❯ uname -a
Darwin M-AI813782 23.3.0 Darwin Kernel Version 23.3.0: Wed Dec 20 21:30:44 PST 2023; root:xnu-10002.81.5~7/RELEASE_ARM64_T6000 arm64
```




Discussion / hints:

Fix patch:
diff --git a/atuin/src/command/client/search/interactive.rs b/atuin/src/command/client/search/interactive.rs
index 1f3a2cff3e9..8c6a672b45a 100644
--- a/atuin/src/command/client/search/interactive.rs
+++ b/atuin/src/command/client/search/interactive.rs
@@ -39,7 +39,7 @@ use ratatui::{
     prelude::*,
     style::{Color, Modifier, Style},
     text::{Line, Span, Text},
-    widgets::{Block, BorderType, Borders, Paragraph, Tabs},
+    widgets::{block::Title, Block, BorderType, Borders, Padding, Paragraph, Tabs},
     Frame, Terminal, TerminalOptions, Viewport,
 };
 
@@ -580,12 +580,26 @@ impl State {
             }
 
             1 => {
-                super::inspector::draw(
-                    f,
-                    results_list_chunk,
-                    &results[self.results_state.selected()],
-                    &stats.expect("Drawing inspector, but no stats"),
-                );
+                if results.is_empty() {
+                    let message = Paragraph::new("Nothing to inspect")
+                        .block(
+                            Block::new()
+                                .title(
+                                    Title::from(" Info ".to_string()).alignment(Alignment::Center),
+                                )
+                                .borders(Borders::ALL)
+                                .padding(Padding::vertical(2)),
+                        )
+                        .alignment(Alignment::Center);
+                    f.render_widget(message, results_list_chunk);
+                } else {
+                    super::inspector::draw(
+                        f,
+                        results_list_chunk,
+                        &results[self.results_state.selected()],
+                        &stats.expect("Drawing inspector, but no stats"),
+                    );
+                }
 
                 // HACK: I'm following up with abstracting this into the UI container, with a
                 // sub-widget for search + for inspector
@@ -988,9 +1002,11 @@ pub async fn history(
 
         stats = if app.tab_index == 0 {
             None
-        } else {
+        } else if !results.is_empty() {
             let selected = results[app.results_state.selected()].clone();
             Some(db.stats(&selected).await?)
+        } else {
+            None
         };
     };
 


Test patch: