Skip to content
Open
Show file tree
Hide file tree
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
8 changes: 6 additions & 2 deletions crates/forge_main/src/zsh/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ pub fn generate_zsh_plugin() -> Result<String> {
output.push_str(&completions_str);

// Set environment variable to indicate plugin is loaded (with timestamp)
output.push_str("\n_FORGE_PLUGIN_LOADED=$(date +%s)\n");
// Use typeset -g so the variable is global even when eval'd inside a function
// (e.g. lazy-loading plugin managers like zinit, zplug, zsh-defer)
output.push_str("\ntypeset -g _FORGE_PLUGIN_LOADED=$(date +%s)\n");

Ok(output)
}
Expand All @@ -54,7 +56,9 @@ pub fn generate_zsh_theme() -> Result<String> {
let mut content = include_str!("../../../../shell-plugin/forge.theme.zsh").to_string();

// Set environment variable to indicate theme is loaded (with timestamp)
content.push_str("\n_FORGE_THEME_LOADED=$(date +%s)\n");
// Use typeset -g so the variable is global even when eval'd inside a function
// (e.g. lazy-loading plugin managers like zinit, zplug, zsh-defer)
content.push_str("\ntypeset -g _FORGE_THEME_LOADED=$(date +%s)\n");

Ok(content)
}
Expand Down
6 changes: 4 additions & 2 deletions shell-plugin/forge.theme.zsh
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#!/usr/bin/env zsh

# Enable prompt substitution for RPROMPT
setopt PROMPT_SUBST
# Use emulate to ensure setopt applies globally even when sourced from a function
emulate -R zsh -c 'setopt PROMPT_SUBST'

# Model and agent info with token count
# Fully formatted output directly from Rust
Expand All @@ -22,6 +23,7 @@ function _forge_prompt_info() {

# Right prompt: agent and model with token count (uses single forge prompt command)
# Set RPROMPT if empty, otherwise append to existing value
# Use typeset -g to ensure RPROMPT is set globally even when sourced from a function
if [[ -z "$_FORGE_THEME_LOADED" ]]; then
RPROMPT='$(_forge_prompt_info)'"${RPROMPT:+ ${RPROMPT}}"
typeset -g RPROMPT='$(_forge_prompt_info)'"${RPROMPT:+ ${RPROMPT}}"
fi
32 changes: 17 additions & 15 deletions shell-plugin/lib/config.zsh
Original file line number Diff line number Diff line change
@@ -1,36 +1,38 @@
#!/usr/bin/env zsh

# Configuration variables for forge plugin
# Using typeset to keep variables local to plugin scope and prevent public exposure
# Using typeset -gh (global + hidden) so variables survive lazy-loading
# from within a function scope (e.g. zinit, zplug, zsh-defer) while
# staying hidden from `typeset` listings.

typeset -h _FORGE_BIN="${FORGE_BIN:-forge}"
typeset -h _FORGE_CONVERSATION_PATTERN=":"
typeset -h _FORGE_MAX_COMMIT_DIFF="${FORGE_MAX_COMMIT_DIFF:-100000}"
typeset -h _FORGE_DELIMITER='\s\s+'
typeset -h _FORGE_PREVIEW_WINDOW="--preview-window=bottom:75%:wrap:border-sharp"
typeset -gh _FORGE_BIN="${FORGE_BIN:-forge}"
typeset -gh _FORGE_CONVERSATION_PATTERN=":"
typeset -gh _FORGE_MAX_COMMIT_DIFF="${FORGE_MAX_COMMIT_DIFF:-100000}"
typeset -gh _FORGE_DELIMITER='\s\s+'
typeset -gh _FORGE_PREVIEW_WINDOW="--preview-window=bottom:75%:wrap:border-sharp"

# Detect fd command - Ubuntu/Debian use 'fdfind', others use 'fd'
typeset -h _FORGE_FD_CMD="$(command -v fdfind 2>/dev/null || command -v fd 2>/dev/null || echo 'fd')"
typeset -gh _FORGE_FD_CMD="$(command -v fdfind 2>/dev/null || command -v fd 2>/dev/null || echo 'fd')"

# Detect bat command - use bat if available, otherwise fall back to cat
if command -v bat &>/dev/null; then
typeset -h _FORGE_CAT_CMD="bat --color=always --style=numbers,changes --line-range=:500"
typeset -gh _FORGE_CAT_CMD="bat --color=always --style=numbers,changes --line-range=:500"
else
typeset -h _FORGE_CAT_CMD="cat"
typeset -gh _FORGE_CAT_CMD="cat"
fi

# Commands cache - loaded lazily on first use
typeset -h _FORGE_COMMANDS=""
typeset -gh _FORGE_COMMANDS=""

# Hidden variables to be used only via the ForgeCLI
typeset -h _FORGE_CONVERSATION_ID
typeset -h _FORGE_ACTIVE_AGENT
typeset -gh _FORGE_CONVERSATION_ID
typeset -gh _FORGE_ACTIVE_AGENT

# Previous conversation ID for :conversation - (like cd -)
typeset -h _FORGE_PREVIOUS_CONVERSATION_ID
typeset -gh _FORGE_PREVIOUS_CONVERSATION_ID

# Session-scoped model and provider overrides (set via :model / :m).
# When non-empty, these are passed as --model / --provider to every forge
# invocation for the lifetime of the current shell session.
typeset -h _FORGE_SESSION_MODEL
typeset -h _FORGE_SESSION_PROVIDER
typeset -gh _FORGE_SESSION_MODEL
typeset -gh _FORGE_SESSION_PROVIDER
8 changes: 8 additions & 0 deletions shell-plugin/lib/highlight.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
# Syntax highlighting configuration for forge commands
# Style the conversation pattern with appropriate highlighting
# Keywords in yellow, rest in default white
#
# Use global declarations so we update the shared zsh-syntax-highlighting
# collections even when sourced from within a function (lazy-loading plugin
# managers). Patterns must remain an associative array because the pattern
# highlighter stores regex => style entries in ZSH_HIGHLIGHT_PATTERNS.

typeset -gA ZSH_HIGHLIGHT_PATTERNS
typeset -ga ZSH_HIGHLIGHT_HIGHLIGHTERS

# Style tagged files
ZSH_HIGHLIGHT_PATTERNS+=('@\[[^]]#\]' 'fg=cyan,bold')
Expand Down
Loading