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

Reply via email to