78 lines
2.2 KiB
Go
78 lines
2.2 KiB
Go
package insert
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"sort"
|
|
)
|
|
|
|
// Preview computes planned insert operations, renders preview output, and returns the summary.
|
|
func Preview(ctx context.Context, req *Request, out io.Writer) (*Summary, []PlannedOperation, error) {
|
|
if req == nil {
|
|
return nil, nil, errors.New("insert request cannot be nil")
|
|
}
|
|
|
|
summary, operations, err := BuildPlan(ctx, req)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
summary.LedgerMetadata["positionToken"] = req.PositionToken
|
|
summary.LedgerMetadata["insertText"] = req.InsertText
|
|
scope := map[string]any{
|
|
"includeDirs": req.IncludeDirs,
|
|
"recursive": req.Recursive,
|
|
"includeHidden": req.IncludeHidden,
|
|
}
|
|
if len(req.ExtensionFilter) > 0 {
|
|
scope["extensionFilter"] = append([]string(nil), req.ExtensionFilter...)
|
|
}
|
|
summary.LedgerMetadata["scope"] = scope
|
|
|
|
if out != nil {
|
|
conflictReasons := make(map[string]string, len(summary.Conflicts))
|
|
for _, conflict := range summary.Conflicts {
|
|
key := conflict.OriginalPath + "->" + conflict.ProposedPath
|
|
conflictReasons[key] = conflict.Reason
|
|
}
|
|
|
|
entries := append([]PreviewEntry(nil), summary.Entries...)
|
|
sort.SliceStable(entries, func(i, j int) bool {
|
|
return entries[i].OriginalPath < entries[j].OriginalPath
|
|
})
|
|
|
|
for _, entry := range entries {
|
|
switch entry.Status {
|
|
case StatusChanged:
|
|
fmt.Fprintf(out, "%s -> %s\n", entry.OriginalPath, entry.ProposedPath)
|
|
case StatusNoChange:
|
|
fmt.Fprintf(out, "%s (no change)\n", entry.OriginalPath)
|
|
case StatusSkipped:
|
|
reason := conflictReasons[entry.OriginalPath+"->"+entry.ProposedPath]
|
|
if reason == "" {
|
|
reason = "skipped"
|
|
}
|
|
fmt.Fprintf(out, "%s -> %s (skipped: %s)\n", entry.OriginalPath, entry.ProposedPath, reason)
|
|
}
|
|
}
|
|
|
|
if summary.TotalCandidates > 0 {
|
|
fmt.Fprintf(out, "\nSummary: %d candidates, %d will change, %d already target position\n",
|
|
summary.TotalCandidates, summary.TotalChanged, summary.NoChange)
|
|
} else {
|
|
fmt.Fprintln(out, "No candidates found.")
|
|
}
|
|
|
|
if len(summary.Warnings) > 0 {
|
|
fmt.Fprintln(out)
|
|
for _, warning := range summary.Warnings {
|
|
fmt.Fprintf(out, "Warning: %s\n", warning)
|
|
}
|
|
}
|
|
}
|
|
|
|
return summary, operations, nil
|
|
}
|