(&mut self, key: KeyEvent)
| 1809 | } |
| 1810 | |
| 1811 | fn handle_logs_key(&mut self, key: KeyEvent) { |
| 1812 | if self.log_detail_index.is_some() { |
| 1813 | match key.code { |
| 1814 | KeyCode::Esc | KeyCode::Enter => { |
| 1815 | self.log_detail_index = None; |
| 1816 | } |
| 1817 | _ => {} |
| 1818 | } |
| 1819 | return; |
| 1820 | } |
| 1821 | |
| 1822 | let filtered_len = self.filtered_log_lines().len(); |
| 1823 | let vh = self.log_viewport_height; |
| 1824 | |
| 1825 | match key.code { |
| 1826 | KeyCode::Esc => { |
| 1827 | if self.log_selection_anchor.is_some() { |
| 1828 | // Cancel visual selection, stay in log viewer. |
| 1829 | self.log_selection_anchor = None; |
| 1830 | } else { |
| 1831 | self.cancel_log_stream(); |
| 1832 | self.log_selection_anchor = None; |
| 1833 | self.focus = Focus::SandboxPolicy; |
| 1834 | } |
| 1835 | } |
| 1836 | KeyCode::Char('q') => self.running = false, |
| 1837 | KeyCode::Char('y') => { |
| 1838 | if filtered_len == 0 { |
| 1839 | return; |
| 1840 | } |
| 1841 | let filtered = self.filtered_log_lines(); |
| 1842 | if let Some(anchor) = self.log_selection_anchor { |
| 1843 | // Visual mode: yank selected range. |
| 1844 | let cursor_abs = self.sandbox_log_scroll + self.log_cursor; |
| 1845 | let start = anchor.min(cursor_abs); |
| 1846 | let end = anchor.max(cursor_abs); |
| 1847 | let text: String = filtered[start..=end.min(filtered.len() - 1)] |
| 1848 | .iter() |
| 1849 | .map(|l| crate::ui::sandbox_logs::format_log_line_plain(l)) |
| 1850 | .collect::<Vec<_>>() |
| 1851 | .join("\n"); |
| 1852 | crate::clipboard::copy_to_clipboard(&text); |
| 1853 | self.log_selection_anchor = None; |
| 1854 | } else { |
| 1855 | // Normal mode: yank current line. |
| 1856 | let abs = self.sandbox_log_scroll + self.log_cursor; |
| 1857 | if let Some(log) = filtered.get(abs) { |
| 1858 | let text = crate::ui::sandbox_logs::format_log_line_plain(log); |
| 1859 | crate::clipboard::copy_to_clipboard(&text); |
| 1860 | } |
| 1861 | } |
| 1862 | } |
| 1863 | KeyCode::Char('Y') => { |
| 1864 | // Yank all visible lines in the viewport. |
| 1865 | if filtered_len == 0 { |
| 1866 | return; |
| 1867 | } |
| 1868 | let filtered = self.filtered_log_lines(); |
no test coverage detected