File size: 4,898 Bytes
c981f27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#!/usr/bin/env zsh

# Terminal context capture for forge plugin
#
# Provides three layers of terminal context:
# 1. preexec/precmd hooks: ring buffer of recent commands + exit codes
# 2. OSC 133 emission: semantic terminal markers for compatible terminals
# 3. Terminal-specific output capture: Kitty > WezTerm > tmux
#
# Context is organized by command blocks: each command's metadata and its
# full output are grouped together, using the known command strings from
# the ring buffer to detect boundaries in the terminal scrollback.

# ---------------------------------------------------------------------------
# OSC 133 helpers
# ---------------------------------------------------------------------------

# Determines whether OSC 133 semantic markers should be emitted.
# Auto-detection is conservative: only emit for terminals known to support it
# to avoid garbled output in unsupported terminals.
# The detection result is cached per session in _FORGE_TERM_OSC133_CACHED
# ("1" = emit, "0" = don't emit) to avoid repeated detection overhead.
typeset -g _FORGE_TERM_OSC133_CACHED=""
function _forge_osc133_should_emit() {
    if [[ -n "$_FORGE_TERM_OSC133_CACHED" ]]; then
        [[ "$_FORGE_TERM_OSC133_CACHED" == "1" ]] && return 0 || return 1
    fi
    case "$_FORGE_TERM_OSC133" in
        on)  _FORGE_TERM_OSC133_CACHED="1"; return 0 ;;
        off) _FORGE_TERM_OSC133_CACHED="0"; return 1 ;;
        auto)
            # Kitty sets KITTY_PID
            if [[ -n "${KITTY_PID:-}" ]]; then _FORGE_TERM_OSC133_CACHED="1"; return 0; fi
            # Detect by TERM_PROGRAM
            case "${TERM_PROGRAM:-}" in
                WezTerm|iTerm.app|vscode|WarpTerminal) _FORGE_TERM_OSC133_CACHED="1"; return 0 ;;
            esac
            # Foot terminal
            if [[ "${TERM:-}" == "foot"* ]]; then _FORGE_TERM_OSC133_CACHED="1"; return 0; fi
            # Ghostty
            if [[ "${TERM_PROGRAM:-}" == "ghostty" ]]; then _FORGE_TERM_OSC133_CACHED="1"; return 0; fi
            # Unknown terminal: don't emit
            _FORGE_TERM_OSC133_CACHED="0"
            return 1
            ;;
        *)   _FORGE_TERM_OSC133_CACHED="0"; return 1 ;;
    esac
}

# Emits an OSC 133 marker if the terminal supports it.
# Usage: _forge_osc133_emit "A"  or  _forge_osc133_emit "D;0"
function _forge_osc133_emit() {
    _forge_osc133_should_emit || return 0
    printf '\e]133;%s\a' "$1"
}

# ---------------------------------------------------------------------------
# preexec / precmd hooks
# ---------------------------------------------------------------------------

# Ring buffer storage uses parallel arrays declared in config.zsh:
#   _FORGE_TERM_COMMANDS, _FORGE_TERM_EXIT_CODES, _FORGE_TERM_TIMESTAMPS
# Pending command state:
typeset -g _FORGE_TERM_PENDING_CMD=""
typeset -g _FORGE_TERM_PENDING_TS=""

# Called before each command executes.
# Records the command text and timestamp, emits OSC 133 B+C markers.
function _forge_context_preexec() {
    [[ "$_FORGE_TERM" != "true" ]] && return
    _FORGE_TERM_PENDING_CMD="$1"
    _FORGE_TERM_PENDING_TS="$(date +%s)"
    # OSC 133 B: prompt end / command start
    _forge_osc133_emit "B"
    # OSC 133 C: command output start
    _forge_osc133_emit "C"
}

# Called after each command completes, before the next prompt is drawn.
# Captures exit code, pushes to ring buffer, emits OSC 133 D+A markers.
function _forge_context_precmd() {
    local last_exit=$?  # MUST be first line to capture exit code

    # OSC 133 D: command finished with exit code.
    # Emitted unconditionally (before the enabled check) so that terminals
    # relying on paired A/B/C/D markers never receive an unpaired sequence,
    # even when context capture is disabled.
    _forge_osc133_emit "D;$last_exit"

    [[ "$_FORGE_TERM" != "true" ]] && return

    # Only record if we have a pending command from preexec
    if [[ -n "$_FORGE_TERM_PENDING_CMD" ]]; then
        _FORGE_TERM_COMMANDS+=("$_FORGE_TERM_PENDING_CMD")
        _FORGE_TERM_EXIT_CODES+=("$last_exit")
        _FORGE_TERM_TIMESTAMPS+=("$_FORGE_TERM_PENDING_TS")

        # Trim ring buffer to max size
        while (( ${#_FORGE_TERM_COMMANDS} > _FORGE_TERM_MAX_COMMANDS )); do
            shift _FORGE_TERM_COMMANDS
            shift _FORGE_TERM_EXIT_CODES
            shift _FORGE_TERM_TIMESTAMPS
        done

        _FORGE_TERM_PENDING_CMD=""
        _FORGE_TERM_PENDING_TS=""
    fi

    # OSC 133 A: prompt start (for the next prompt)
    _forge_osc133_emit "A"
}

# Hook registration

# Register using standard zsh hook arrays for coexistence with other plugins.
# precmd is prepended so it runs first and captures the real $? from the
# command, before other plugins (powerlevel10k, starship, etc.) overwrite it.
if [[ "$_FORGE_TERM" == "true" ]]; then
    preexec_functions+=(_forge_context_preexec)
    precmd_functions=(_forge_context_precmd "${precmd_functions[@]}")
fi