terrazzo-terminal 0.2.8

A simple web-based terminal emulator built on Terrazzo.
use std::path::Path;
use std::sync::Arc;

use terrazzo::prelude::diagnostics;

use self::diagnostics::debug;
use crate::text_editor::file_path::FilePath;
use crate::text_editor::notify::manager::SideViewNotify;
use crate::text_editor::side::SideViewList;
use crate::text_editor::side::SideViewNode;
use crate::text_editor::side::SvnItem;
use crate::text_editor::side::SvnProperties;
use crate::text_editor::side::SvnStatus;
use crate::text_editor::side::opaque::OpaqueNotifyRegistration;

pub fn add_node_rec<'l>(
    manager: &impl SideViewNotify,
    path: &FilePath<Arc<Path>>,
    make: impl FnOnce(Option<&SideViewNode>) -> Option<SideViewNode>,
    mut relative_path: impl Iterator<Item = &'l Path>,
    node: Option<&SideViewNode>,
) -> Option<SideViewNode> {
    let next = relative_path.next();
    debug!(?path, ?next, ?node, "Add node rec");
    let next = match next {
        None => return make(node),
        Some(item) => item,
    };
    let (mut properties, folder, notify) = parse_folder(manager, path, node);
    let (folder, status) = add_node_rec_folder(manager, path, make, relative_path, &folder, next)?;
    if status == SvnStatus::Active {
        properties.status = status;
    }
    Some(SideViewNode {
        properties,
        item: SvnItem::Folder {
            folder: folder.into(),
            notify,
        },
    })
}

fn add_node_rec_folder<'l>(
    manager: &impl SideViewNotify,
    path: &FilePath<Arc<Path>>,
    make: impl FnOnce(Option<&SideViewNode>) -> Option<SideViewNode>,
    relative_path: impl Iterator<Item = &'l Path>,
    folder: &SideViewList,
    folder_name: &Path,
) -> Option<(SideViewList, SvnStatus)> {
    let child = add_node_rec(
        manager,
        path,
        make,
        relative_path,
        folder.get(folder_name).map(Arc::as_ref),
    )?;
    let status = child.properties.status;
    let mut folder = folder.clone();
    folder.insert(folder_name.into(), child.into());
    (folder, status).into()
}

fn parse_folder(
    manager: &impl SideViewNotify,
    path: &FilePath<Arc<Path>>,
    node: Option<&SideViewNode>,
) -> (SvnProperties, Arc<SideViewList>, OpaqueNotifyRegistration) {
    match node {
        Some(node) => {
            let (folder, notify) = match &node.item {
                SvnItem::Folder { folder, notify } => (folder.clone(), notify.clone()),
                SvnItem::File { metadata: _ } => {
                    (Default::default(), manager.watch_side_view_folder(path))
                }
            };
            (node.properties.clone(), folder, notify)
        }
        None => (
            SvnProperties {
                status: SvnStatus::Active,
            },
            Default::default(),
            manager.watch_side_view_folder(path),
        ),
    }
}