Files

65 lines
2.3 KiB
Go

// Copyright (c) 2026 Storm Dragon
// SPDX-License-Identifier: GPL-3.0-or-later
package reader
import (
"slices"
"strings"
"time"
"unicode"
"git.stormux.org/storm/fenrir/internal/presentation"
"git.stormux.org/storm/fenrir/internal/screen"
)
func (r *Reader) Configure_indentation(mode string) { r.indentationMode = mode }
func (r *Reader) indentation_feedback(announce bool) *presentation.Message {
level, valid := r.review.Indentation()
if !valid {
return nil // Blank rows preserve the last meaningful level.
}
changed := r.indentKnown && level != r.lastIndent
r.lastIndent, r.indentKnown = level, true
if !announce || !changed || r.indentationMode == "" || r.indentationMode == "none" {
return nil
}
message := presentation.Indentation_message(level, r.indentationMode)
return &message
}
func (r *Reader) automatic_indentation(previous, next screen.Snapshot, switched bool) *presentation.Message {
if switched {
r.indentKnown = false
}
// Passive program output must not create indentation chatter. Match Python's
// cursor-input window and suppress automatic cursor feedback during review.
announce := !switched && next.Active && r.automatic && r.cursorEcho && r.trackingMode == "cursor" && !r.review.Active() &&
r.region_state().allows(next.X, next.Y, next.Cols, true, true) &&
!r.applicationInputAt.IsZero() && time.Since(r.applicationInputAt) < 300*time.Millisecond
if announce {
// A hidden leading-whitespace edit must not produce indentation cues
// at an otherwise visible cursor farther along the same row.
for col, char := range next.Line(next.Y) {
if !r.region_state().allows(col, next.Y, next.Cols, true, true) {
announce = false
break
}
if !unicode.IsSpace(char) {
break
}
}
}
if announce && previous.Y == next.Y {
// Horizontal input only reports a genuine leading-whitespace edit, not
// movement within a line or ordinary typing/deletion in its content.
before, after := previous.Text(previous.Y), next.Text(next.Y)
announce = strings.TrimSpace(before) == strings.TrimSpace(after) && before != after
} else if announce {
// A cursor moving with new program output is not line navigation.
announce = slices.Equal(previous.Line(next.Y), next.Line(next.Y))
}
return r.indentation_feedback(announce)
}