You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "Adriano Machado (Jira)" <ji...@apache.org> on 2026/06/24 19:42:00 UTC
[jira] [Comment Edited] (CAMEL-23829) camel-jbang - TUI shell panel: add a scrollbar to indicate scrollback position
[ https://issues.apache.org/jira/browse/CAMEL-23829?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18091297#comment-18091297 ]
Adriano Machado edited comment on CAMEL-23829 at 6/24/26 7:41 PM:
------------------------------------------------------------------
h3. Root cause: scrollback history is unreachable on released JLine
{{ShellPanel}} reads the shell scrollback through two reflective helpers:
{code:java}
ScreenTerminal.class.getMethod("getHistory")
ScreenTerminal.class.getMethod("getHistorySize")
{code}
{{Class.getMethod(...)}} only resolves *public* methods. In {{{}org.jline.utils.ScreenTerminal{}}}, the scrollback lives in a *private* field with no public accessor:
{code:java}
private List<long[]> history = new ArrayList<>(); // populated as lines scroll off the top
{code}
Verified against both *JLine 4.2.1* (the version Camel currently uses) and the {*}JLine {{master}} branch{*}: {{getHistory()}} / {{getHistorySize()}} do not exist as public, protected, or package-private members in either. So both reflective lookups throw {{{}NoSuchMethodException{}}}, the {{catch}} swallows it, and they return {{0}} / empty on every call.
h3. Consequences
* The scrollbar is gated on {{{}histSize > 0{}}}. Since {{histSize}} is always {{{}0{}}}, {{{}totalLines == innerHeight{}}}, the {{totalLines > innerHeight}} guard is never true, and the scrollbar never draws.
* The pre-existing *Shift+PgUp / Shift+PgDn* and *mouse-wheel* scrollback (added in CAMEL-23727) are equally inert: {{{}scrollOffset = min(.., 0) = 0{}}}, so they silently no-op. Scrollback has never actually functioned on a released JLine.
h3. Why there is no easy workaround
* {{dump()}} (all overloads) only ever returns the {*}visible viewport{*}, never the {{history}} buffer.
* Subclassing {{ScreenTerminal}} cannot reach the data: {{history}} is {{{}private{}}}, and the methods that populate it are {{private}} too.
* A Camel-owned scrollback buffer would require diffing successive dumps or re-parsing VT100, i.e. reimplementing the emulator. Not viable.
The {{history}} data exists and is correctly maintained; it is simply fully encapsulated with no accessor.
h3. Why not Aesh's terminal? (re: CAMEL-23810)
Migrating the command framework from picocli to Aesh does *not* help here, and dropping JLine in favour of Aesh's terminal would regress the shell panel. Aesh has plenty of terminal machinery, but not the specific piece {{ShellPanel}} relies on:
* Aesh's core terminal abstraction ({{{}org.aesh.terminal.Connection{}}}) is a *streaming transport* (stdin/stdout handlers, size, signals, capabilities). It has no addressable screen and no {{{}dump(){}}}.
* Aesh *does* ship a scrollback buffer: {{{}org.aesh.terminal.tty.split.ScrollbackBuffer{}}}, used by its split-screen regions ({{{}SplitScreen{}}} / {{{}ScreenRegion{}}}). It is bounded and thread-safe, with {{addLine(String)}} / {{{}getLastLines(int){}}}. But it stores *plain {{String}} lines explicitly written to a region* — it does not VT100-emulate a raw output stream, so it carries no cursor model and no per-cell colour/style attributes.
* The {{Buffer}} / {{ConsoleBuffer}} / {{AeshConsoleBuffer}} classes are the readline *line-edit* buffer (cursor position, {{{}insert{}}}, {{asString}} of the current input line), not screen history. {{TerminalString}} / {{ANSIBuilder}} / {{HtmlAnsiOutputStream}} are one-way ANSI *formatters* that emit escape sequences and retain no parsed screen. {{org.aesh.readline.history.History}} is *command-input* history (the typed command lines recalled with up/down), not output scrollback.
* {{ShellPanel}} needs none of those: it runs a *child interactive shell* and must parse that child's raw VT100 byte stream into an addressable, attributed cell grid (cursor moves, colours, clears, alternate screen) and read it back each frame to composite into TamboUI. JLine's {{ScreenTerminal}} is exactly that headless VT100 emulator (a {{long[]}} cell grid plus {{{}history{}}}). Feeding Aesh's text-only {{ScrollbackBuffer}} would still require emulating the stream into lines first, and would drop styling and full-screen apps.
In short, Aesh provides a command driver ({{{}AeshConsoleRunner{}}}), a streaming transport ({{{}Connection{}}}), an interactive pager ({{{}PagingSupport{}}}), ANSI output formatting, command-input history, and even a text scrollback buffer — but no headless VT100 screen emulator that turns a child's raw output into a readable, attributed cell buffer. That piece, which {{ShellPanel}} depends on, today only JLine provides.
h3. Suggested path forward ([JLine|https://github.com/jline/jline3/pull/1996])
Expose the scrollback in JLine via a {{synchronized}} {{getHistory()}} (returning a snapshot) and {{{}getHistorySize(){}}}, release it, then bump {{jline-version}} in Camel and replace the reflection with the real calls. The existing {{ShellPanel}} scrollbar and scrollback wiring would then work unchanged.
[Pull request|https://github.com/apache/camel/pull/24236] was closed due to this new finding.
_Claude Code on behalf of Adriano Machado_
was (Author: ammachado):
h3. Root cause: scrollback history is unreachable on released JLine
{{ShellPanel}} reads the shell scrollback through two reflective helpers:
{code:java}
ScreenTerminal.class.getMethod("getHistory")
ScreenTerminal.class.getMethod("getHistorySize")
{code}
{{Class.getMethod(...)}} only resolves *public* methods. In {{org.jline.utils.ScreenTerminal}}, the scrollback lives in a *private* field with no public accessor:
{code:java}
private List<long[]> history = new ArrayList<>(); // populated as lines scroll off the top
{code}
Verified against both *JLine 4.2.1* (the version Camel currently uses) and the *JLine {{master}} branch*: {{getHistory()}} / {{getHistorySize()}} do not exist as public, protected, or package-private members in either. So both reflective lookups throw {{NoSuchMethodException}}, the {{catch}} swallows it, and they return {{0}} / empty on every call.
h3. Consequences
* The scrollbar is gated on {{histSize > 0}}. Since {{histSize}} is always {{0}}, {{totalLines == innerHeight}}, the {{totalLines > innerHeight}} guard is never true, and the scrollbar never draws.
* The pre-existing *Shift+PgUp / Shift+PgDn* and *mouse-wheel* scrollback (added in CAMEL-23727) are equally inert: {{scrollOffset = min(.., 0) = 0}}, so they silently no-op. Scrollback has never actually functioned on a released JLine.
h3. Why there is no easy workaround
* {{dump()}} (all overloads) only ever returns the *visible viewport*, never the {{history}} buffer.
* Subclassing {{ScreenTerminal}} cannot reach the data: {{history}} is {{private}}, and the methods that populate it are {{private}} too.
* A Camel-owned scrollback buffer would require diffing successive dumps or re-parsing VT100, i.e. reimplementing the emulator. Not viable.
The {{history}} data exists and is correctly maintained; it is simply fully encapsulated with no accessor.
h3. Why not Aesh's terminal? (re: CAMEL-23810)
Migrating the command framework from picocli to Aesh does *not* help here, and dropping JLine in favour of Aesh's terminal would regress the shell panel. Aesh has plenty of terminal machinery, but not the specific piece {{ShellPanel}} relies on:
* Aesh's core terminal abstraction ({{org.aesh.terminal.Connection}}) is a *streaming transport* (stdin/stdout handlers, size, signals, capabilities). It has no addressable screen and no {{dump()}}.
* Aesh *does* ship a scrollback buffer: {{org.aesh.terminal.tty.split.ScrollbackBuffer}}, used by its split-screen regions ({{SplitScreen}} / {{ScreenRegion}}). It is bounded and thread-safe, with {{addLine(String)}} / {{getLastLines(int)}}. But it stores *plain {{String}} lines explicitly written to a region* — it does not VT100-emulate a raw output stream, so it carries no cursor model and no per-cell colour/style attributes.
* The {{Buffer}} / {{ConsoleBuffer}} / {{AeshConsoleBuffer}} classes are the readline *line-edit* buffer (cursor position, {{insert}}, {{asString}} of the current input line), not screen history. {{TerminalString}} / {{ANSIBuilder}} / {{HtmlAnsiOutputStream}} are one-way ANSI *formatters* that emit escape sequences and retain no parsed screen. {{org.aesh.readline.history.History}} is *command-input* history (the typed command lines recalled with up/down), not output scrollback.
* {{ShellPanel}} needs none of those: it runs a *child interactive shell* and must parse that child's raw VT100 byte stream into an addressable, attributed cell grid (cursor moves, colours, clears, alternate screen) and read it back each frame to composite into TamboUI. JLine's {{ScreenTerminal}} is exactly that headless VT100 emulator (a {{long[]}} cell grid plus {{history}}). Feeding Aesh's text-only {{ScrollbackBuffer}} would still require emulating the stream into lines first, and would drop styling and full-screen apps.
In short, Aesh provides a command driver ({{AeshConsoleRunner}}), a streaming transport ({{Connection}}), an interactive pager ({{PagingSupport}}), ANSI output formatting, command-input history, and even a text scrollback buffer — but no headless VT100 screen emulator that turns a child's raw output into a readable, attributed cell buffer. That piece, which {{ShellPanel}} depends on, today only JLine provides.
h3. Suggested path forward
Expose the scrollback in JLine via a {{synchronized}} {{getHistory()}} (returning a snapshot) and {{getHistorySize()}}, release it, then bump {{jline-version}} in Camel and replace the reflection with the real calls. The existing {{ShellPanel}} scrollbar and scrollback wiring would then work unchanged.
[Pull request|https://github.com/apache/camel/pull/24236] was closed due to this new finding.
_Claude Code on behalf of Adriano Machado_
> camel-jbang - TUI shell panel: add a scrollbar to indicate scrollback position
> ------------------------------------------------------------------------------
>
> Key: CAMEL-23829
> URL: https://issues.apache.org/jira/browse/CAMEL-23829
> Project: Camel
> Issue Type: Improvement
> Components: camel-jbang
> Reporter: Adriano Machado
> Priority: Major
>
> The embedded JLine shell
> panel in the Camel TUI \(camel\-jbang, ShellPanel\) supports scrollback via Shift\+PageUp/PageDown and the mouse wheel, but renders no visual scrollbar. There is no affordance
> showing the current position within the scrollback history.
> Other TUI tabs \(Log, Source viewer, Diagram, Configuration, History\) already render a vertical scrollbar using
> tamboui Scrollbar / ScrollbarState via a horizontal layout split \(content fill \+ 1\-column scrollbar\). The shell panel should follow the same pattern for
> consistency.
> Acceptance: a vertical scrollbar appears on the shell panel reflecting scroll position when scrollback content exceeds the viewport.
> _Filed by Claude Code
> on behalf of Adriano Machado._
--
This message was sent by Atlassian Jira
(v8.20.10#820010)