[
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)