Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 45 additions & 12 deletions crates/forge_main/src/completer/input_completer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,7 @@ impl Completer for InputCompleter {
.map(|file| file.path)
.collect();

// Preview command: show directory listing for dirs, file contents for files.
// {2} references the path column (items are formatted as "{idx}\t{path}").
// Use bat for syntax-highlighted file previews when available, falling back
// to cat. Mirrors the shell plugin's _FORGE_CAT_CMD and completion.zsh preview.
let cat_cmd = if which_bat() {
"bat --color=always --style=numbers,changes --line-range=:500"
} else {
"cat"
};
let preview_cmd = format!(
"if [ -d {{2}} ]; then ls -la --color=always {{2}} 2>/dev/null || ls -la {{2}}; else {cat_cmd} {{2}}; fi"
);
let preview_cmd = build_preview_cmd(cat_cmd_for_preview());

let mut builder = ForgeWidget::select("File", files)
.with_preview(preview_cmd)
Expand Down Expand Up @@ -87,3 +76,47 @@ fn which_bat() -> bool {
.map(|o| o.status.success())
.unwrap_or(false)
}

/// Prefers `bat` for syntax-highlighted output when it is on `$PATH`, falling
/// back to plain `cat`. Mirrors the shell plugin's `_FORGE_CAT_CMD`.
fn cat_cmd_for_preview() -> &'static str {
if which_bat() {
"bat --color=always --style=numbers,changes --line-range=:500"
} else {
"cat"
}
}

/// Builds the fzf `--preview` command as `sh -c '…' _ {2}`.
///
/// Wrapping in `sh -c` is required because fzf dispatches previews through
/// `$SHELL`, and shells like fish cannot parse the POSIX `if/then/fi` body.
/// `{2}` is fzf's substitution for the tab-separated path column.
fn build_preview_cmd(cat_cmd: &str) -> String {
format!(
r#"sh -c 'if [ -d "$1" ]; then ls -la --color=always "$1" 2>/dev/null || ls -la "$1"; else {cat_cmd} "$1"; fi' _ {{2}}"#
)
}

#[cfg(test)]
mod tests {
use pretty_assertions::assert_eq;

use super::*;

#[test]
fn test_build_preview_cmd_with_cat() {
let fixture = "cat";
let actual = build_preview_cmd(fixture);
let expected = r#"sh -c 'if [ -d "$1" ]; then ls -la --color=always "$1" 2>/dev/null || ls -la "$1"; else cat "$1"; fi' _ {2}"#;
assert_eq!(actual, expected);
}

#[test]
fn test_build_preview_cmd_with_bat() {
let fixture = "bat --color=always --style=numbers,changes --line-range=:500";
let actual = build_preview_cmd(fixture);
let expected = r#"sh -c 'if [ -d "$1" ]; then ls -la --color=always "$1" 2>/dev/null || ls -la "$1"; else bat --color=always --style=numbers,changes --line-range=:500 "$1"; fi' _ {2}"#;
assert_eq!(actual, expected);
}
}
Loading