Skip to main content

rec/import/
importer.rs

1//! Core import logic: read file, detect format, parse, and save session.
2
3use crate::error::{RecError, Result};
4use crate::models::{Command, Session, SessionStatus};
5use crate::storage::SessionStore;
6use std::path::Path;
7
8use super::detect::{ImportFormat, detect_format, session_name_from_path};
9use super::{bash_history, bash_script, fish_history, zsh_history};
10
11/// Result of a successful import operation.
12#[derive(Debug)]
13pub struct ImportResult {
14    /// Name of the created session
15    pub session_name: String,
16    /// Number of commands imported
17    pub command_count: usize,
18    /// Detected import format
19    pub format: ImportFormat,
20    /// Preview of first 5 commands
21    pub preview_commands: Vec<String>,
22}
23
24/// Import a file into a rec session.
25///
26/// Detects format, parses commands, creates a completed Session,
27/// saves it via `SessionStore`, and returns an `ImportResult` with preview.
28///
29/// # Errors
30///
31/// Returns an error if the file cannot be read, the format is unsupported,
32/// or the session cannot be saved to the store.
33pub fn import_file(
34    path: &Path,
35    name_override: Option<&str>,
36    store: &SessionStore,
37) -> Result<ImportResult> {
38    let content = std::fs::read_to_string(path)?;
39    let path_str = path.to_string_lossy();
40
41    let format = detect_format(&path_str, &content)?;
42
43    let commands: Vec<String> = match format {
44        ImportFormat::BashScript => bash_script::parse_bash_script(&content),
45        ImportFormat::BashHistory => bash_history::parse_bash_history(&content),
46        ImportFormat::ZshHistory => zsh_history::parse_zsh_history(&content),
47        ImportFormat::FishHistory => fish_history::parse_fish_history(&content),
48    };
49
50    if commands.is_empty() {
51        return Err(RecError::InvalidSession(
52            "No commands found in file".to_string(),
53        ));
54    }
55
56    let session_name = match name_override {
57        Some(name) => name.to_string(),
58        None => session_name_from_path(path),
59    };
60
61    let command_count = commands.len();
62    let preview_commands: Vec<String> = commands.iter().take(5).cloned().collect();
63
64    // Create session with commands
65    let mut session = Session::new(&session_name);
66    let cwd = std::env::current_dir().unwrap_or_else(|_| std::path::PathBuf::from("/"));
67
68    for (i, cmd_text) in commands.iter().enumerate() {
69        let cmd = Command::new(i as u32, cmd_text.clone(), cwd.clone());
70        session.add_command(cmd);
71    }
72    session.complete(SessionStatus::Completed);
73
74    store.save(&session)?;
75
76    Ok(ImportResult {
77        session_name,
78        command_count,
79        format,
80        preview_commands,
81    })
82}