Skip to main content

Crate llimphi_module_fif

Crate llimphi_module_fif 

Source
Expand description

llimphi-module-fif — find-in-files reutilizable (estilo JetBrains).

Módulo Llimphi con dos vistas independientes:

  • view_dialog — popup compacto (header + input) que el host pinta como overlay modal centrado. Sólo visible cuando FifState::dialog_open es true.
  • view_results_bar — barra inferior persistente con la lista de matches. El host la pinta como tool window al pie (estilo JetBrains “Find” tool window). Sobrevive al cierre del dialog: el user puede Esc-cerrar el popup y seguir clickeando los resultados.

El flujo típico es: Ctrl+Shift+F abre el dialog → tipear → Enter ejecuta search → resultados aparecen en la barra inferior → Esc cierra el popup pero la barra queda → click en una fila abre el archivo. Re-disparar Ctrl+Shift+F reabre el popup conservando los últimos resultados.

§Cómo lo enchufa una app

struct AppModel {
    all_files: Vec<PathBuf>,
    fif: Option<FifState>,
    // …
}

enum AppMsg { Fif(llimphi_module_fif::FifMsg), … }

// En update(model, msg):
AppMsg::Fif(fm) => {
    // Lazy-init en Open:
    if matches!(fm, FifMsg::Open) && model.fif.is_none() {
        model.fif = Some(FifState::new());
    } else if matches!(fm, FifMsg::Open) {
        model.fif.as_mut().unwrap().dialog_open = true;
    }
    let action = match model.fif.as_mut() {
        Some(s) => llimphi_module_fif::apply(s, fm, &model.all_files),
        None => FifAction::None,
    };
    match action {
        FifAction::None => {}
        FifAction::CloseDialog => {
            if let Some(s) = model.fif.as_mut() { s.dialog_open = false; }
        }
        FifAction::CloseAll => model.fif = None,
        FifAction::Searched { .. } => { /* actualizar status bar */ }
        FifAction::OpenAt { path, line, col } => {
            if let Some(s) = model.fif.as_mut() { s.dialog_open = false; }
            open_path_in_app(path, line, col);
        }
    }
}

// En on_key(model, event): solo rutea cuando el dialog está visible.
if let Some(state) = model.fif.as_ref() {
    if let Some(fm) = llimphi_module_fif::on_key(state, event) {
        return Some(AppMsg::Fif(fm));
    }
}
if llimphi_module_fif::open_shortcut(event) {
    return Some(AppMsg::Fif(FifMsg::Open));
}

// En view(model):
//   - dialog como overlay arriba del editor:
if let Some(s) = model.fif.as_ref().filter(|s| s.dialog_open) {
    overlay_children.push(view_dialog(s, &palette, AppMsg::Fif));
}
//   - barra de resultados como panel inferior persistente:
if let Some(s) = model.fif.as_ref().filter(|s| !s.results.is_empty()) {
    bottom_panels.push(view_results_bar(
        s, &model.all_files, &model.root, &palette, AppMsg::Fif,
    ));
}

§Por qué Action en lugar de un trait FifHost

El módulo no toma &mut Host porque acoplar el módulo a un trait arrastra problemas de ownership/lifetimes en el loop tipo Elm que usa Llimphi (Model se mueve por value en update). Devolver una FifAction deja al host libre de aplicar el efecto donde y como quiera, y mantiene al módulo libre de cualquier conocimiento sobre el host.

Structs§

FifMatch
Un match individual.
FifPalette
Paleta visual. Construible desde un llimphi_theme::Theme.
FifState
Estado interno del módulo.

Enums§

FifAction
Efecto solicitado al host. El módulo nunca toca el FS ni el resto del modelo de la app — devuelve el deseo, el host elige cómo lo aplica.
FifFocus
Qué input tiene el foco dentro del dialog. Tab alterna.
FifMsg
Vocabulario interno. El host lo wrapea en su propio Msg.

Constants§

CAPABILITIES
Capabilities que este módulo aporta al host. Convención del protocolo Brahman Card aplicada a módulos compile-time: el host (cuando construye su [card_core::Card]) puede agregar esto a provides para anunciar — vía broker — que su instancia ofrece find-in-files al ecosistema.
MAX_FILE_SIZE
MAX_RESULTS
Caps razonables para que un workspace grande no funda el UI.
MIN_QUERY_LEN
SNIPPET_MAX_CHARS

Functions§

apply
Aplica un mensaje al estado y retorna el efecto que el host debe ejecutar.
on_key
Routing de teclas cuando el dialog está abierto. Si el popup está cerrado, devuelve None y el host puede seguir routeando al editor.
open_shortcut
Chequea si el evento es el atajo recomendado: Ctrl+Shift+F. El host puede ignorar esto y definir su propio binding.
replace_all
Reemplazo case-insensitive sobre los archivos involucrados en results. Devuelve (files_changed, replacements, failures). Lee cada archivo una sola vez, sustituye todas las apariciones de query por replacement (case-insensitive, preservando el resto), y escribe sólo si hubo cambios. No toca buffers en memoria del host — el host es responsable de recargar tabs si quiere ver los cambios.
search
Búsqueda substring case-insensitive. Pública para tests / hosts que quieran disparar una búsqueda sin pasar por el state machine.
view_dialog
Popup modal compacto: header + input. Sin lista de resultados — esa vive en view_results_bar. El host lo pinta como overlay centrado.
view_results_bar
Barra inferior persistente con los matches. Filas clickeables (click → FifMsg::ActivateAt). El host la pinta como tool window al pie del editor, hermana del terminal/output (estilo JetBrains).