This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch feat/camel-tui in repository https://gitbox.apache.org/repos/asf/camel.git
commit 8ae8d8908215c60726bde854b6eea22fa26abe36 Author: Claus Ibsen <[email protected]> AuthorDate: Mon May 18 16:46:48 2026 +0200 TUI: spec viewer scrolls to HTTP verb declaration, not just operationId line When pressing 'c' to view an OpenAPI spec, walk backwards from the operationId line to find the enclosing HTTP verb declaration (get:/post: etc.) by detecting the first line at a shallower indentation that matches an OpenAPI verb. Supports both YAML and JSON specs. Falls back to the operationId line if no verb line is found. Co-Authored-By: Claude Sonnet 4.6 <[email protected]> --- .../dsl/jbang/core/commands/tui/CamelMonitor.java | 61 ++++++++++++++++++++-- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java index a6c0dbba1dae..7bd985e0b4aa 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java +++ b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java @@ -3850,20 +3850,75 @@ public class CamelMonitor extends CamelCommand { List<String> lines = List.of(content.split("\n", -1)); - // scroll to the line containing operationId int scrollTo = 0; if (operationId != null) { + // Find the line that declares this operationId + int opIdLine = -1; for (int i = 0; i < lines.size(); i++) { - if (lines.get(i).contains(operationId)) { - scrollTo = Math.max(0, i - 2); + String line = lines.get(i); + // match both YAML (operationId: foo) and JSON ("operationId": "foo") + if (line.contains("operationId") && line.contains(operationId)) { + opIdLine = i; break; } } + if (opIdLine >= 0) { + scrollTo = findOperationDeclarationLine(lines, opIdLine); + } } applySpecResult(specUri, lines, scrollTo); } + private static final Set<String> OPENAPI_HTTP_VERBS + = Set.of("get", "post", "put", "delete", "patch", "options", "head", "trace"); + + /** + * Walk backwards from the operationId line to find where the HTTP verb declaration starts (e.g. "get:" in YAML or + * '"get":' in JSON). Returns the line index to scroll to. + */ + private static int findOperationDeclarationLine(List<String> lines, int opIdLine) { + int opIdIndent = leadingSpaces(lines.get(opIdLine)); + for (int i = opIdLine - 1; i >= 0; i--) { + String raw = lines.get(i); + String trimmed = raw.trim(); + if (trimmed.isEmpty()) { + continue; + } + int indent = leadingSpaces(raw); + if (indent >= opIdIndent) { + continue; // still inside the operation body + } + // Check if this line is an HTTP verb (YAML: "get:" / JSON: '"get":') + String lower = trimmed.toLowerCase(Locale.ENGLISH); + for (String verb : OPENAPI_HTTP_VERBS) { + if (lower.equals(verb + ":") || lower.startsWith(verb + ": ") + || lower.equals("\"" + verb + "\":") || lower.startsWith("\"" + verb + "\": ")) { + return Math.max(0, i - 1); // show one line of context above + } + } + // Hit something at a shallower indent that isn't a verb (e.g. a path key) — stop + break; + } + // Fallback: scroll to operationId line with a couple lines of context + return Math.max(0, opIdLine - 2); + } + + private static int leadingSpaces(String line) { + int count = 0; + for (int i = 0; i < line.length(); i++) { + char c = line.charAt(i); + if (c == ' ') { + count++; + } else if (c == '\t') { + count += 2; + } else { + break; + } + } + return count; + } + private void applySpecResult(String specUri, List<String> lines, int scrollTo) { if (runner == null) { return;
