1pub mod archive;
2pub mod binary;
3pub mod diff;
4pub mod directory;
5pub mod doc;
6pub mod encoding;
7pub mod image;
8pub mod media;
9pub mod pdf;
10pub mod protocol;
11pub mod request;
12pub mod rich_text;
13pub mod sqlite;
14pub mod structured_log;
15pub mod types;
16pub mod worker;
17
18use ratatui_image::picker::Picker;
19use std::time::Duration;
20
21const PREVIEW_COMMAND_POLL_INTERVAL: Duration = Duration::from_millis(50);
22const PREVIEW_COMMAND_TIMEOUT: Duration = Duration::from_secs(2);
23
24pub fn spawn_previewer(
29 rx_request: impl crate::infra::channel::Receiver<PreviewRequest> + 'static,
30 tx_preview: impl crate::infra::channel::Sender<(PreviewSource, PreviewContent)> + 'static,
31 tx_log: impl crate::infra::channel::Sender<(String, Vec<LogEntry>)> + 'static,
32 picker: Picker,
33 preview_command: Option<String>,
34 delimiter: String,
35 log_max_entries: usize,
36) {
37 std::thread::spawn(move || {
38 let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
42 let executor = worker::executor::PreviewExecutor::new(
43 picker,
44 preview_command,
45 delimiter,
46 log_max_entries,
47 );
48 let mut orchestrator = worker::orchestrator::PreviewOrchestrator::new(
49 rx_request, tx_preview, tx_log, executor,
50 );
51 orchestrator.run();
52 }));
53
54 if let Err(panic_info) = result {
55 let msg = if let Some(s) = panic_info.downcast_ref::<String>() {
56 s.clone()
57 } else if let Some(s) = panic_info.downcast_ref::<&str>() {
58 s.to_string()
59 } else {
60 "unknown panic in preview worker".to_string()
61 };
62 eprintln!("Preview worker panicked: {}", msg);
63 }
64 });
65}
66
67fn build_path_preview(path_str: &str, picker: &Picker, log_max_entries: usize) -> PreviewContent {
68 request::path::registry::build_path_preview(path_str, picker, log_max_entries)
69}
70
71pub(super) fn apply_param_substitutions(arg: &str, item: &str, parts: &[&str]) -> String {
83 let mut result = arg.to_string();
84 for (i, part) in parts.iter().enumerate() {
85 result = result.replace(&format!("{{{i}}}"), part);
86 }
87 result.replace("{}", item)
88}
89
90pub use protocol::{PreviewRequest, PreviewSource};
91pub use rich_text::syntax::{
92 detect_language, get_configs, get_highlighter, get_style, SyntaxRegistry,
93};
94pub use rich_text::RichTextDocument;
95pub use rich_text::{
96 apply_text_edit, create_rich_text_document, edit_content_delete_char,
97 edit_content_delete_char_at, edit_content_delete_range, edit_content_insert_char,
98 edit_content_insert_text, generate_plain_lines_for_range, regenerate_lines,
99};
100pub use structured_log::LogEntry;
101pub use types::{DiffPreview, ImagePreview, LogPreview, MediaPreview, PreviewContent};