Skip to content

Commit d6cef99

Browse files
authored
Merge pull request #11 from Daniel-Ric/feature/2026-02-03/enhance-tool-with-ip-lookup-options-yxm4e0
Selection-Menüs in-place rendern
2 parents 3666490 + 4cc2a7f commit d6cef99

3 files changed

Lines changed: 74 additions & 47 deletions

File tree

internal/cli/cli.go

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ type App struct {
1717

1818
func NewApp() *App {
1919
return &App{
20-
inputTimeout: 3 * time.Second,
21-
lookupTimeout: 45 * time.Second,
20+
inputTimeout: 3 * time.Second,
2221
}
2322
}
2423

@@ -308,23 +307,21 @@ func (a *App) executeDirect(config DirectConfig) error {
308307
}
309308

310309
func (a *App) executeLookup(config LookupConfig) error {
311-
ctx, cancel := context.WithTimeout(context.Background(), a.lookupTimeout)
312-
defer cancel()
310+
ctx := context.Background()
313311

314312
resultText, err := withSpinner("IP Lookup", "Domains werden überprüft", 120*time.Millisecond, func() (string, error) {
315313
result, lookupErr := ping.LookupDomains(ctx, ping.LookupConfig{
316-
Edition: config.Edition,
317-
Port: config.Port,
318-
BaseHost: config.BaseHost,
319-
Subdomains: config.Subdomains,
320-
DomainEndings: config.Endings,
321-
Concurrency: 24,
322-
PerHostTimeout: 2 * time.Second,
314+
Edition: config.Edition,
315+
Port: config.Port,
316+
BaseHost: config.BaseHost,
317+
Subdomains: config.Subdomains,
318+
DomainEndings: config.Endings,
319+
Concurrency: 24,
323320
})
324-
if lookupErr != nil && !errors.Is(lookupErr, context.DeadlineExceeded) {
321+
if lookupErr != nil {
325322
return "", lookupErr
326323
}
327-
return formatLookupResult(result, errors.Is(lookupErr, context.DeadlineExceeded)), nil
324+
return formatLookupResult(result), nil
328325
})
329326
if err != nil {
330327
return err
@@ -342,13 +339,10 @@ func (a *App) askAgain() (bool, error) {
342339
return index == 0, nil
343340
}
344341

345-
func formatLookupResult(result ping.LookupResult, timedOut bool) string {
342+
func formatLookupResult(result ping.LookupResult) string {
346343
var builder strings.Builder
347344
builder.WriteString(fmt.Sprintf("Kombinationen geprüft: %d/%d\n", result.Completed, result.Attempts))
348345
builder.WriteString(fmt.Sprintf("Treffer: %d\n", len(result.Matches)))
349-
if timedOut {
350-
builder.WriteString("Hinweis: Zeitlimit erreicht, Ergebnisse können unvollständig sein.\n")
351-
}
352346
builder.WriteString("\n")
353347

354348
if len(result.Matches) == 0 {

internal/cli/ui.go

Lines changed: 56 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ func selectOption(title string, options []string) (int, error) {
6565
defer restore(fd, state)
6666

6767
selected := 0
68-
renderMenu(title, options, selected, "")
68+
lines := renderMenuBlock(title, options, selected, "", true)
6969

7070
reader := bufio.NewReader(os.Stdin)
7171
for {
@@ -81,12 +81,12 @@ func selectOption(title string, options []string) (int, error) {
8181
if selected > 0 {
8282
selected--
8383
}
84-
renderMenu(title, options, selected, "")
84+
lines = updateMenu(title, options, selected, "", lines)
8585
case 's', 'j':
8686
if selected < len(options)-1 {
8787
selected++
8888
}
89-
renderMenu(title, options, selected, "")
89+
lines = updateMenu(title, options, selected, "", lines)
9090
case 13, 10:
9191
clearScreen()
9292
return selected, nil
@@ -105,7 +105,7 @@ func selectOption(title string, options []string) (int, error) {
105105
selected++
106106
}
107107
}
108-
renderMenu(title, options, selected, "")
108+
lines = updateMenu(title, options, selected, "", lines)
109109
case 0, 224:
110110
code, err := reader.ReadByte()
111111
if err != nil {
@@ -117,7 +117,7 @@ func selectOption(title string, options []string) (int, error) {
117117
if code == 80 && selected < len(options)-1 {
118118
selected++
119119
}
120-
renderMenu(title, options, selected, "")
120+
lines = updateMenu(title, options, selected, "", lines)
121121
}
122122
}
123123
}
@@ -141,22 +141,50 @@ func readEscapeSequence(reader *bufio.Reader) (string, error) {
141141
return string([]byte{b1, b2}), nil
142142
}
143143

144-
func renderMenu(title string, options []string, selected int, hint string) {
145-
clearScreen()
146-
fmt.Println(style(title, colorAccent))
147-
fmt.Println()
144+
func renderMenuBlock(title string, options []string, selected int, hint string, clear bool) int {
145+
if clear {
146+
clearScreen()
147+
}
148+
lines := 0
149+
lines += printLine(style(title, colorAccent))
150+
lines += printLine("")
148151
for i, option := range options {
149152
if i == selected {
150-
fmt.Printf("%s %s\n", style(">", colorAccent+colorBold), style(option, colorBold))
153+
lines += printLine(fmt.Sprintf("%s %s", style(">", colorAccent+colorBold), style(option, colorBold)))
151154
continue
152155
}
153-
fmt.Printf(" %s\n", option)
156+
lines += printLine(fmt.Sprintf(" %s", option))
154157
}
155-
fmt.Println()
158+
lines += printLine("")
156159
if hint == "" {
157160
hint = "Pfeiltasten (oder W/S), Enter zum Bestätigen"
158161
}
159-
fmt.Println(style(hint, colorDim))
162+
lines += printLine(style(hint, colorDim))
163+
return lines
164+
}
165+
166+
func updateMenu(title string, options []string, selected int, hint string, lines int) int {
167+
if lines > 0 {
168+
moveCursorUp(lines)
169+
}
170+
return renderMenuBlock(title, options, selected, hint, false)
171+
}
172+
173+
func printLine(value string) int {
174+
clearLine()
175+
fmt.Println(value)
176+
return 1
177+
}
178+
179+
func clearLine() {
180+
fmt.Print("\r\033[K")
181+
}
182+
183+
func moveCursorUp(lines int) {
184+
if lines <= 0 {
185+
return
186+
}
187+
fmt.Printf("\033[%dA", lines)
160188
}
161189

162190
func clearScreen() {
@@ -198,17 +226,31 @@ func withSpinner(title, message string, tick time.Duration, action func() (strin
198226
}{result: result, err: err}
199227
}()
200228

229+
clearScreen()
230+
fmt.Println(style(title, colorAccent))
231+
fmt.Println()
232+
201233
frames := []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}
202234
ticker := time.NewTicker(tick)
203235
defer ticker.Stop()
204236

205237
frame := 0
238+
lastLen := 0
206239
for {
207240
select {
208241
case res := <-resultCh:
242+
if lastLen > 0 {
243+
fmt.Print("\r", strings.Repeat(" ", lastLen), "\r")
244+
}
245+
fmt.Println()
209246
return res.result, res.err
210247
case <-ticker.C:
211-
renderSpinnerPage(title, message, frames[frame])
248+
line := fmt.Sprintf("%s %s", style(message, colorDim), style(frames[frame], colorAccent))
249+
if lastLen > 0 && len(line) < lastLen {
250+
line += strings.Repeat(" ", lastLen-len(line))
251+
}
252+
fmt.Print("\r", line)
253+
lastLen = len(line)
212254
frame = (frame + 1) % len(frames)
213255
}
214256
}

internal/ping/lookup.go

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,15 @@ import (
66
"strings"
77
"sync"
88
"sync/atomic"
9-
"time"
109
)
1110

1211
type LookupConfig struct {
13-
Edition Edition
14-
Port int
15-
BaseHost string
16-
Subdomains []string
17-
DomainEndings []string
18-
Concurrency int
19-
PerHostTimeout time.Duration
12+
Edition Edition
13+
Port int
14+
BaseHost string
15+
Subdomains []string
16+
DomainEndings []string
17+
Concurrency int
2018
}
2119

2220
type LookupMatch struct {
@@ -49,11 +47,6 @@ func LookupDomains(ctx context.Context, config LookupConfig) (LookupResult, erro
4947
if concurrency <= 0 {
5048
concurrency = 16
5149
}
52-
perHostTimeout := config.PerHostTimeout
53-
if perHostTimeout <= 0 {
54-
perHostTimeout = 2 * time.Second
55-
}
56-
5750
total := len(subdomains) * len(endings)
5851
if total == 0 {
5952
return LookupResult{}, fmt.Errorf("keine kombinationen verfügbar")
@@ -73,9 +66,7 @@ func LookupDomains(ctx context.Context, config LookupConfig) (LookupResult, erro
7366
default:
7467
}
7568

76-
hostCtx, cancel := context.WithTimeout(ctx, perHostTimeout)
77-
res, err := Execute(hostCtx, config.Edition, host, config.Port)
78-
cancel()
69+
res, err := Execute(ctx, config.Edition, host, config.Port)
7970
atomic.AddInt64(&completed, 1)
8071
if err != nil {
8172
continue

0 commit comments

Comments
 (0)