mirror of
https://github.com/lukaszraczylo/kportal.git
synced 2026-06-30 05:44:37 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 518879dc56 | |||
| 649227b201 | |||
| 28e2fc315a |
+1
-1
@@ -56,7 +56,7 @@ release:
|
|||||||
brews:
|
brews:
|
||||||
- repository:
|
- repository:
|
||||||
owner: lukaszraczylo
|
owner: lukaszraczylo
|
||||||
name: brew-taps
|
name: homebrew-taps
|
||||||
token: "{{ .Env.HOMEBREW_TAP_TOKEN }}"
|
token: "{{ .Env.HOMEBREW_TAP_TOKEN }}"
|
||||||
directory: Formula
|
directory: Formula
|
||||||
homepage: https://lukaszraczylo.github.io/kportal
|
homepage: https://lukaszraczylo.github.io/kportal
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ kportal manages multiple Kubernetes port-forwards with an interactive terminal i
|
|||||||
### Homebrew (macOS/Linux)
|
### Homebrew (macOS/Linux)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
brew install lukaszraczylo/brew-taps/kportal
|
brew install lukaszraczylo/taps/kportal
|
||||||
```
|
```
|
||||||
|
|
||||||
### Quick Install
|
### Quick Install
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
kportal.raczylo.com
|
||||||
+2
-2
@@ -559,8 +559,8 @@
|
|||||||
<p class="text-gray-600 dark:text-gray-400 text-sm">macOS & Linux</p>
|
<p class="text-gray-600 dark:text-gray-400 text-sm">macOS & Linux</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div onclick="copyToClipboard('brew install lukaszraczylo/brew-taps/kportal', this)" class="relative bg-gradient-to-br from-gray-900 to-gray-800 dark:from-gray-950 dark:to-black text-gray-100 p-4 rounded-lg text-sm cursor-pointer group overflow-x-auto border border-gray-700 hover:border-orange-500 transition-all duration-300">
|
<div onclick="copyToClipboard('brew install lukaszraczylo/taps/kportal', this)" class="relative bg-gradient-to-br from-gray-900 to-gray-800 dark:from-gray-950 dark:to-black text-gray-100 p-4 rounded-lg text-sm cursor-pointer group overflow-x-auto border border-gray-700 hover:border-orange-500 transition-all duration-300">
|
||||||
<code class="block whitespace-nowrap font-mono">brew install lukaszraczylo/brew-taps/kportal</code>
|
<code class="block whitespace-nowrap font-mono">brew install lukaszraczylo/taps/kportal</code>
|
||||||
<div class="absolute top-3 right-3"><i class="fas fa-copy text-gray-500 group-hover:text-orange-400 transition-colors duration-300"></i></div>
|
<div class="absolute top-3 right-3"><i class="fas fa-copy text-gray-500 group-hover:text-orange-400 transition-colors duration-300"></i></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+82
-15
@@ -602,20 +602,82 @@ func (m model) renderMainView() string {
|
|||||||
footerStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("240"))
|
footerStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("240"))
|
||||||
keyStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("220"))
|
keyStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("220"))
|
||||||
|
|
||||||
footer := fmt.Sprintf("%s/%s: Navigate %s: Toggle %s: New %s: Edit %s: Delete %s: Bench %s: Logs %s: Quit │ Total: %d",
|
// Get terminal width for footer wrapping
|
||||||
keyStyle.Render("↑↓"),
|
termWidth := m.termWidth
|
||||||
keyStyle.Render("jk"),
|
if termWidth == 0 {
|
||||||
keyStyle.Render("Space"),
|
termWidth = 120
|
||||||
keyStyle.Render("n"),
|
}
|
||||||
keyStyle.Render("e"),
|
|
||||||
keyStyle.Render("d"),
|
|
||||||
keyStyle.Render("b"),
|
|
||||||
keyStyle.Render("l"),
|
|
||||||
keyStyle.Render("q"),
|
|
||||||
len(m.ui.forwardOrder))
|
|
||||||
|
|
||||||
// Fill space to push footer to bottom (reserve 2 lines: 1 for spacing, 1 for footer)
|
// Define key bindings as structured data for flexible rendering
|
||||||
footerHeight := 2
|
type keyBinding struct {
|
||||||
|
key string
|
||||||
|
desc string
|
||||||
|
}
|
||||||
|
bindings := []keyBinding{
|
||||||
|
{"↑↓/jk", "Navigate"},
|
||||||
|
{"Space", "Toggle"},
|
||||||
|
{"n", "New"},
|
||||||
|
{"e", "Edit"},
|
||||||
|
{"d", "Delete"},
|
||||||
|
{"b", "Bench"},
|
||||||
|
{"l", "Logs"},
|
||||||
|
{"q", "Quit"},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build footer lines that fit within terminal width
|
||||||
|
var footerLines []string
|
||||||
|
var currentLine strings.Builder
|
||||||
|
currentLineVisualLen := 0
|
||||||
|
|
||||||
|
// Calculate how much space we need for the total count suffix
|
||||||
|
totalSuffix := fmt.Sprintf(" │ Total: %d", len(m.ui.forwardOrder))
|
||||||
|
totalSuffixLen := len(totalSuffix)
|
||||||
|
|
||||||
|
// Available width (account for some margin)
|
||||||
|
availableWidth := termWidth - 4
|
||||||
|
|
||||||
|
for i, binding := range bindings {
|
||||||
|
// Build this binding's text
|
||||||
|
keyRendered := keyStyle.Render(binding.key)
|
||||||
|
bindingText := keyRendered + ": " + binding.desc
|
||||||
|
// Visual length without ANSI codes
|
||||||
|
bindingVisualLen := len(binding.key) + 2 + len(binding.desc)
|
||||||
|
|
||||||
|
// Add separator if not first item on line
|
||||||
|
separator := ""
|
||||||
|
separatorLen := 0
|
||||||
|
if currentLine.Len() > 0 {
|
||||||
|
separator = " "
|
||||||
|
separatorLen = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this binding fits on current line
|
||||||
|
// For the last binding, also need to fit the total suffix
|
||||||
|
neededWidth := currentLineVisualLen + separatorLen + bindingVisualLen
|
||||||
|
if i == len(bindings)-1 {
|
||||||
|
neededWidth += totalSuffixLen
|
||||||
|
}
|
||||||
|
|
||||||
|
if neededWidth > availableWidth && currentLine.Len() > 0 {
|
||||||
|
// Start a new line
|
||||||
|
footerLines = append(footerLines, currentLine.String())
|
||||||
|
currentLine.Reset()
|
||||||
|
currentLineVisualLen = 0
|
||||||
|
separator = ""
|
||||||
|
separatorLen = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
currentLine.WriteString(separator)
|
||||||
|
currentLine.WriteString(bindingText)
|
||||||
|
currentLineVisualLen += separatorLen + bindingVisualLen
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add total count to the last line
|
||||||
|
currentLine.WriteString(totalSuffix)
|
||||||
|
footerLines = append(footerLines, currentLine.String())
|
||||||
|
|
||||||
|
// Calculate footer height
|
||||||
|
footerHeight := len(footerLines) + 1 // +1 for the blank line before footer
|
||||||
remainingLines := termHeight - currentLines - footerHeight
|
remainingLines := termHeight - currentLines - footerHeight
|
||||||
if remainingLines > 0 {
|
if remainingLines > 0 {
|
||||||
b.WriteString(strings.Repeat("\n", remainingLines))
|
b.WriteString(strings.Repeat("\n", remainingLines))
|
||||||
@@ -623,7 +685,12 @@ func (m model) renderMainView() string {
|
|||||||
|
|
||||||
// Add footer at bottom
|
// Add footer at bottom
|
||||||
b.WriteString("\n")
|
b.WriteString("\n")
|
||||||
b.WriteString(footerStyle.Render(footer))
|
for i, line := range footerLines {
|
||||||
|
if i > 0 {
|
||||||
|
b.WriteString("\n")
|
||||||
|
}
|
||||||
|
b.WriteString(footerStyle.Render(line))
|
||||||
|
}
|
||||||
|
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
@@ -736,7 +803,7 @@ func (m model) renderDeleteConfirmation() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b.WriteString("\n\n")
|
b.WriteString("\n\n")
|
||||||
b.WriteString(helpStyle.Render("←/→: Navigate Enter: Confirm Esc: Cancel"))
|
b.WriteString(wrapHelpText("←/→: Navigate Enter: Confirm Esc: Cancel", wizardHelpWidth(m.termWidth)))
|
||||||
|
|
||||||
// Wrap in a box using wizard style
|
// Wrap in a box using wizard style
|
||||||
boxStyle := lipgloss.NewStyle().
|
boxStyle := lipgloss.NewStyle().
|
||||||
|
|||||||
@@ -194,6 +194,96 @@ func renderTextInput(label, value string, valid bool) string {
|
|||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wizardHelpWidth returns an appropriate width for wizard help text
|
||||||
|
// based on terminal width. For modals, we use a sensible maximum.
|
||||||
|
func wizardHelpWidth(termWidth int) int {
|
||||||
|
if termWidth == 0 {
|
||||||
|
termWidth = 80
|
||||||
|
}
|
||||||
|
// Wizard modals shouldn't be wider than 70 chars typically
|
||||||
|
// but on narrow terminals, use available space minus padding
|
||||||
|
maxWidth := 70
|
||||||
|
available := termWidth - 10 // account for modal borders and padding
|
||||||
|
if available < maxWidth {
|
||||||
|
return available
|
||||||
|
}
|
||||||
|
return maxWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
// wrapHelpText wraps help text to fit within the given width.
|
||||||
|
// Help text is expected to be in the format "key: action key: action ..."
|
||||||
|
// separated by double spaces. On smaller screens, it wraps to multiple lines.
|
||||||
|
func wrapHelpText(text string, width int) string {
|
||||||
|
if width <= 0 {
|
||||||
|
width = 80 // Default width
|
||||||
|
}
|
||||||
|
|
||||||
|
// Account for some padding/margin
|
||||||
|
availableWidth := width - 4
|
||||||
|
if availableWidth < 20 {
|
||||||
|
availableWidth = 20
|
||||||
|
}
|
||||||
|
|
||||||
|
// If text fits, return as-is
|
||||||
|
if len(text) <= availableWidth {
|
||||||
|
return helpStyle.Render(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split by double-space separator (common in help text)
|
||||||
|
parts := strings.Split(text, " ")
|
||||||
|
if len(parts) <= 1 {
|
||||||
|
// No double-space separators, just truncate
|
||||||
|
if len(text) > availableWidth-3 {
|
||||||
|
return helpStyle.Render(text[:availableWidth-3] + "...")
|
||||||
|
}
|
||||||
|
return helpStyle.Render(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
var lines []string
|
||||||
|
var currentLine strings.Builder
|
||||||
|
|
||||||
|
for i, part := range parts {
|
||||||
|
part = strings.TrimSpace(part)
|
||||||
|
if part == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if adding this part would exceed width
|
||||||
|
addition := part
|
||||||
|
if currentLine.Len() > 0 {
|
||||||
|
addition = " " + part
|
||||||
|
}
|
||||||
|
|
||||||
|
if currentLine.Len()+len(addition) > availableWidth && currentLine.Len() > 0 {
|
||||||
|
// Start new line
|
||||||
|
lines = append(lines, currentLine.String())
|
||||||
|
currentLine.Reset()
|
||||||
|
currentLine.WriteString(part)
|
||||||
|
} else {
|
||||||
|
if currentLine.Len() > 0 {
|
||||||
|
currentLine.WriteString(" ")
|
||||||
|
}
|
||||||
|
currentLine.WriteString(part)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle last part
|
||||||
|
if i == len(parts)-1 && currentLine.Len() > 0 {
|
||||||
|
lines = append(lines, currentLine.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Join with newlines and apply style to each line
|
||||||
|
var result strings.Builder
|
||||||
|
for i, line := range lines {
|
||||||
|
if i > 0 {
|
||||||
|
result.WriteString("\n")
|
||||||
|
}
|
||||||
|
result.WriteString(helpStyle.Render(line))
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.String()
|
||||||
|
}
|
||||||
|
|
||||||
// overlayContent overlays modal content centered on the base view
|
// overlayContent overlays modal content centered on the base view
|
||||||
// Note: base parameter is kept for API compatibility but not used since
|
// Note: base parameter is kept for API compatibility but not used since
|
||||||
// lipgloss.Place provides cleaner centering without background artifacts
|
// lipgloss.Place provides cleaner centering without background artifacts
|
||||||
|
|||||||
+29
-24
@@ -109,10 +109,11 @@ func (m model) renderSelectContext() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b.WriteString("\n")
|
b.WriteString("\n")
|
||||||
|
helpWidth := wizardHelpWidth(m.termWidth)
|
||||||
if wizard.searchFilter != "" {
|
if wizard.searchFilter != "" {
|
||||||
b.WriteString(helpStyle.Render(fmt.Sprintf("↑/↓: Navigate Enter: Select Backspace: Clear filter (%d/%d) Esc: Cancel", len(wizard.getFilteredContexts()), len(wizard.contexts))))
|
b.WriteString(wrapHelpText(fmt.Sprintf("↑/↓: Navigate Enter: Select Backspace: Clear filter (%d/%d) Esc: Cancel", len(wizard.getFilteredContexts()), len(wizard.contexts)), helpWidth))
|
||||||
} else {
|
} else {
|
||||||
b.WriteString(helpStyle.Render("Type to filter ↑/↓: Navigate Enter: Select Esc/Ctrl+C: Cancel"))
|
b.WriteString(wrapHelpText("Type to filter ↑/↓: Navigate Enter: Select Esc/Ctrl+C: Cancel", helpWidth))
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.String()
|
return b.String()
|
||||||
@@ -150,10 +151,11 @@ func (m model) renderSelectNamespace() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b.WriteString("\n")
|
b.WriteString("\n")
|
||||||
|
helpWidth := wizardHelpWidth(m.termWidth)
|
||||||
if wizard.searchFilter != "" {
|
if wizard.searchFilter != "" {
|
||||||
b.WriteString(helpStyle.Render(fmt.Sprintf("↑/↓: Navigate Enter: Select Backspace: Clear filter (%d/%d) Esc: Back", len(wizard.getFilteredNamespaces()), len(wizard.namespaces))))
|
b.WriteString(wrapHelpText(fmt.Sprintf("↑/↓: Navigate Enter: Select Backspace: Clear filter (%d/%d) Esc: Back", len(wizard.getFilteredNamespaces()), len(wizard.namespaces)), helpWidth))
|
||||||
} else {
|
} else {
|
||||||
b.WriteString(helpStyle.Render("Type to filter ↑/↓: Navigate Enter: Select Esc: Back Ctrl+C: Cancel"))
|
b.WriteString(wrapHelpText("Type to filter ↑/↓: Navigate Enter: Select Esc: Back Ctrl+C: Cancel", helpWidth))
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.String()
|
return b.String()
|
||||||
@@ -192,7 +194,7 @@ func (m model) renderSelectResourceType() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b.WriteString("\n")
|
b.WriteString("\n")
|
||||||
b.WriteString(helpStyle.Render("↑/↓: Navigate Enter: Select Esc: Back Ctrl+C: Cancel"))
|
b.WriteString(wrapHelpText("↑/↓: Navigate Enter: Select Esc: Back Ctrl+C: Cancel", wizardHelpWidth(m.termWidth)))
|
||||||
|
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
@@ -305,14 +307,15 @@ func (m model) renderEnterResource() string {
|
|||||||
|
|
||||||
b.WriteString("\n")
|
b.WriteString("\n")
|
||||||
// Show appropriate help text based on resource type and filter state
|
// Show appropriate help text based on resource type and filter state
|
||||||
|
helpWidth := wizardHelpWidth(m.termWidth)
|
||||||
if wizard.selectedResourceType == ResourceTypeService {
|
if wizard.selectedResourceType == ResourceTypeService {
|
||||||
if wizard.searchFilter != "" {
|
if wizard.searchFilter != "" {
|
||||||
b.WriteString(helpStyle.Render(fmt.Sprintf("↑/↓: Navigate Enter: Select Backspace: Clear filter (%d/%d) Esc: Back", len(wizard.getFilteredServices()), len(wizard.services))))
|
b.WriteString(wrapHelpText(fmt.Sprintf("↑/↓: Navigate Enter: Select Backspace: Clear filter (%d/%d) Esc: Back", len(wizard.getFilteredServices()), len(wizard.services)), helpWidth))
|
||||||
} else {
|
} else {
|
||||||
b.WriteString(helpStyle.Render("Type to filter ↑/↓: Navigate Enter: Select Esc: Back Ctrl+C: Cancel"))
|
b.WriteString(wrapHelpText("Type to filter ↑/↓: Navigate Enter: Select Esc: Back Ctrl+C: Cancel", helpWidth))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
b.WriteString(helpStyle.Render("Enter: Continue Esc: Back Ctrl+C: Cancel"))
|
b.WriteString(wrapHelpText("Enter: Continue Esc: Back Ctrl+C: Cancel", helpWidth))
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.String()
|
return b.String()
|
||||||
@@ -403,7 +406,7 @@ func (m model) renderEnterRemotePort() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b.WriteString("\n")
|
b.WriteString("\n")
|
||||||
b.WriteString(helpStyle.Render("↑/↓: Navigate Enter: Select Esc: Back Ctrl+C: Cancel"))
|
b.WriteString(wrapHelpText("↑/↓: Navigate Enter: Select Esc: Back Ctrl+C: Cancel", wizardHelpWidth(m.termWidth)))
|
||||||
} else {
|
} else {
|
||||||
// Text input mode (no detected ports or user chose manual entry)
|
// Text input mode (no detected ports or user chose manual entry)
|
||||||
if len(wizard.detectedPorts) > 0 {
|
if len(wizard.detectedPorts) > 0 {
|
||||||
@@ -436,7 +439,7 @@ func (m model) renderEnterRemotePort() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b.WriteString("\n")
|
b.WriteString("\n")
|
||||||
b.WriteString(helpStyle.Render("Enter: Continue Esc: Back Ctrl+C: Cancel"))
|
b.WriteString(wrapHelpText("Enter: Continue Esc: Back Ctrl+C: Cancel", wizardHelpWidth(m.termWidth)))
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.String()
|
return b.String()
|
||||||
@@ -477,7 +480,7 @@ func (m model) renderEnterLocalPort() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b.WriteString("\n")
|
b.WriteString("\n")
|
||||||
b.WriteString(helpStyle.Render("Enter: Continue Esc: Back Ctrl+C: Cancel"))
|
b.WriteString(wrapHelpText("Enter: Continue Esc: Back Ctrl+C: Cancel", wizardHelpWidth(m.termWidth)))
|
||||||
|
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
@@ -535,7 +538,7 @@ func (m model) renderConfirmation() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b.WriteString("\n")
|
b.WriteString("\n")
|
||||||
b.WriteString(helpStyle.Render("↑/↓/Tab: Navigate Enter: Confirm Esc: Back"))
|
b.WriteString(wrapHelpText("↑/↓/Tab: Navigate Enter: Confirm Esc: Back", wizardHelpWidth(m.termWidth)))
|
||||||
|
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
@@ -578,7 +581,7 @@ func (m model) renderSuccess() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b.WriteString("\n")
|
b.WriteString("\n")
|
||||||
b.WriteString(helpStyle.Render("↑/↓: Navigate Enter: Select"))
|
b.WriteString(wrapHelpText("↑/↓: Navigate Enter: Select", wizardHelpWidth(m.termWidth)))
|
||||||
|
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
@@ -641,7 +644,7 @@ func (m model) renderRemoveSelection() string {
|
|||||||
selectedCount := wizard.getSelectedCount()
|
selectedCount := wizard.getSelectedCount()
|
||||||
b.WriteString(fmt.Sprintf("%d of %d selected\n\n", selectedCount, len(wizard.forwards)))
|
b.WriteString(fmt.Sprintf("%d of %d selected\n\n", selectedCount, len(wizard.forwards)))
|
||||||
|
|
||||||
b.WriteString(helpStyle.Render("Space: Toggle a: All n: None Enter: Remove Esc: Cancel"))
|
b.WriteString(wrapHelpText("Space: Toggle a: All n: None Enter: Remove Esc: Cancel", wizardHelpWidth(m.termWidth)))
|
||||||
|
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
@@ -676,7 +679,7 @@ func (m model) renderRemoveConfirmation() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b.WriteString("\n")
|
b.WriteString("\n")
|
||||||
b.WriteString(helpStyle.Render("↑/↓: Navigate Enter: Confirm Esc: Cancel"))
|
b.WriteString(wrapHelpText("↑/↓: Navigate Enter: Confirm Esc: Cancel", wizardHelpWidth(m.termWidth)))
|
||||||
|
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
@@ -740,7 +743,7 @@ func (m model) renderBenchmarkConfig() string {
|
|||||||
b.WriteString("\n")
|
b.WriteString("\n")
|
||||||
b.WriteString(mutedStyle.Render(fmt.Sprintf("Will send %d requests with %d concurrent workers", state.requests, state.concurrency)))
|
b.WriteString(mutedStyle.Render(fmt.Sprintf("Will send %d requests with %d concurrent workers", state.requests, state.concurrency)))
|
||||||
b.WriteString("\n\n")
|
b.WriteString("\n\n")
|
||||||
b.WriteString(helpStyle.Render("↑/↓/Tab: Navigate Type to edit Enter: Run Esc: Cancel"))
|
b.WriteString(wrapHelpText("↑/↓/Tab: Navigate Type to edit Enter: Run Esc: Cancel", wizardHelpWidth(m.termWidth)))
|
||||||
|
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
@@ -780,7 +783,7 @@ func (m model) renderBenchmarkRunning() string {
|
|||||||
b.WriteString(mutedStyle.Render(fmt.Sprintf("Method: %s Concurrency: %d", state.method, state.concurrency)))
|
b.WriteString(mutedStyle.Render(fmt.Sprintf("Method: %s Concurrency: %d", state.method, state.concurrency)))
|
||||||
b.WriteString("\n\n")
|
b.WriteString("\n\n")
|
||||||
|
|
||||||
b.WriteString(helpStyle.Render("Please wait..."))
|
b.WriteString(wrapHelpText("Please wait...", wizardHelpWidth(m.termWidth)))
|
||||||
|
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
@@ -796,14 +799,14 @@ func (m model) renderBenchmarkResults() string {
|
|||||||
if state.error != nil {
|
if state.error != nil {
|
||||||
b.WriteString(errorStyle.Render(fmt.Sprintf("✗ Error: %v", state.error)))
|
b.WriteString(errorStyle.Render(fmt.Sprintf("✗ Error: %v", state.error)))
|
||||||
b.WriteString("\n\n")
|
b.WriteString("\n\n")
|
||||||
b.WriteString(helpStyle.Render("Press Enter or Esc to return"))
|
b.WriteString(wrapHelpText("Press Enter or Esc to return", wizardHelpWidth(m.termWidth)))
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
if state.results == nil {
|
if state.results == nil {
|
||||||
b.WriteString(mutedStyle.Render("No results available"))
|
b.WriteString(mutedStyle.Render("No results available"))
|
||||||
b.WriteString("\n\n")
|
b.WriteString("\n\n")
|
||||||
b.WriteString(helpStyle.Render("Press Enter or Esc to return"))
|
b.WriteString(wrapHelpText("Press Enter or Esc to return", wizardHelpWidth(m.termWidth)))
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -872,7 +875,7 @@ func (m model) renderBenchmarkResults() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b.WriteString("\n")
|
b.WriteString("\n")
|
||||||
b.WriteString(helpStyle.Render("Press Enter or Esc to return"))
|
b.WriteString(wrapHelpText("Press Enter or Esc to return", wizardHelpWidth(m.termWidth)))
|
||||||
|
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
@@ -1076,8 +1079,10 @@ func (m model) renderHTTPLog() string {
|
|||||||
}
|
}
|
||||||
b.WriteString("\n")
|
b.WriteString("\n")
|
||||||
|
|
||||||
// Help line at bottom
|
// Help line at bottom (wrap for smaller screens)
|
||||||
b.WriteString(helpStyle.Render(" ↑/↓: Navigate Enter: Details a: Auto-scroll f: Filter /: Search c: Clear q: Close"))
|
helpText := "↑/↓: Navigate Enter: Details a: Auto-scroll f: Filter /: Search c: Clear q: Close"
|
||||||
|
b.WriteString(" ")
|
||||||
|
b.WriteString(wrapHelpText(helpText, termWidth-4))
|
||||||
|
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
@@ -1273,9 +1278,9 @@ func (m model) renderHTTPLogDetail(entry HTTPLogEntry, termWidth, termHeight int
|
|||||||
if state.copyMessage != "" {
|
if state.copyMessage != "" {
|
||||||
b.WriteString(successStyle.Render(state.copyMessage))
|
b.WriteString(successStyle.Render(state.copyMessage))
|
||||||
b.WriteString(" ")
|
b.WriteString(" ")
|
||||||
b.WriteString(helpStyle.Render("↑/↓: Scroll c: Copy Esc: Back"))
|
b.WriteString(wrapHelpText("↑/↓: Scroll c: Copy Esc: Back", termWidth-10))
|
||||||
} else {
|
} else {
|
||||||
b.WriteString(helpStyle.Render("↑/↓/PgUp/PgDn: Scroll g: Top c: Copy response Esc: Back"))
|
b.WriteString(wrapHelpText("↑/↓/PgUp/PgDn: Scroll g: Top c: Copy response Esc: Back", termWidth-10))
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.String()
|
return b.String()
|
||||||
|
|||||||
Reference in New Issue
Block a user