Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,21 @@ the message, consistent with the inbound header filtering already performed by t

Ordinary application headers are unaffected. If a route relied on `Camel*` headers being propagated from the MIME
content, set them explicitly after unmarshalling.

=== camel-jbang catalog tables fill the terminal width

The `camel catalog` commands (`camel catalog component`, `camel catalog dataformat`,
`camel catalog language`, `camel catalog transformer`, `camel catalog kamelet`, ...) now size the
`DESCRIPTION` column to the detected terminal width instead of the previous fixed 80-character cap,
so wide terminals show more of the description before it is truncated with an ellipsis. The `NAME`
column width is also standardized across these commands (it previously differed per command, for
example 60 for `transformer` and 30 elsewhere).

Terminal width is now detected on Windows (`cmd` / PowerShell) via `mode con`, in addition to the
existing `COLUMNS` / `stty size` detection. When no terminal can be detected (for example when the
output is piped or redirected), the width falls back to 120 columns. For full, untruncated output
suitable for scripting, use the `--json` option.

The `camel infra list` table now sizes its `DESCRIPTION` column to the terminal width, and truncates
the `IMPLEMENTATION` and `SERVICE_DATA` columns with an ellipsis instead of letting the raw service
data overflow the terminal. The complete, structured service data remains available via `--json`.
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,19 @@
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.function.Function;
import java.util.stream.Collectors;

import com.github.freva.asciitable.AsciiTable;
import com.github.freva.asciitable.Column;
import com.github.freva.asciitable.HorizontalAlign;
import com.github.freva.asciitable.OverflowBehaviour;
import org.apache.camel.catalog.CamelCatalog;
import org.apache.camel.catalog.DefaultCamelCatalog;
import org.apache.camel.dsl.jbang.core.commands.CamelCommand;
import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
import org.apache.camel.dsl.jbang.core.commands.MavenResolverMixin;
import org.apache.camel.dsl.jbang.core.commands.QuarkusPlatformMixin;
import org.apache.camel.dsl.jbang.core.common.CamelTableColumns;
import org.apache.camel.dsl.jbang.core.common.CatalogLoader;
import org.apache.camel.dsl.jbang.core.common.RuntimeCompletionCandidates;
import org.apache.camel.dsl.jbang.core.common.RuntimeType;
Expand Down Expand Up @@ -159,27 +160,28 @@ public Integer doCall() throws Exception {
.map(CatalogBaseDTO::toMap)
.collect(Collectors.toList())));
} else {
// Compute description width: terminal minus fixed columns and border overhead
int fixedWidth = nameWidth() + 12 + 8; // LEVEL ~12 chars, SINCE ~8 chars
if (RuntimeType.quarkus == runtime) {
fixedWidth += 8; // NATIVE column
}
int descWidth = TerminalWidthHelper.flexWidth(
terminalWidth(), fixedWidth, TerminalWidthHelper.noBorderOverhead(
RuntimeType.quarkus == runtime ? 5 : 4),
20, 80);
// Size the DESCRIPTION column to fill the terminal: measure the actual width of the other
// visible columns and give the remainder to DESCRIPTION (floored on narrow terminals).
boolean quarkus = RuntimeType.quarkus == runtime;
Function<Row, String> nameGetter = displayGav ? this::shortGav : r -> r.name;
int nameW = CamelTableColumns.measure(displayGav ? "ARTIFACT-ID" : "NAME",
displayGav ? Integer.MAX_VALUE : CamelTableColumns.NAME_MAX, rows, nameGetter);
int levelW = CamelTableColumns.measure("LEVEL", Integer.MAX_VALUE, rows, this::level);
int sinceW = CamelTableColumns.measure("SINCE", Integer.MAX_VALUE, rows, r -> r.since);
int overhead = TerminalWidthHelper.noBorderOverhead(quarkus ? 5 : 4);
int descWidth = quarkus
? CamelTableColumns.lastColumnWidth(terminalWidth(), overhead, nameW, levelW, sinceW,
CamelTableColumns.measure("NATIVE", Integer.MAX_VALUE, rows, this::nativeSupported))
: CamelTableColumns.lastColumnWidth(terminalWidth(), overhead, nameW, levelW, sinceW);
printer().println(AsciiTable.getTable(AsciiTable.NO_BORDERS, rows, Arrays.asList(
new Column().header("NAME").visible(!displayGav).dataAlign(HorizontalAlign.LEFT).maxWidth(nameWidth())
.with(r -> r.name),
CamelTableColumns.name().visible(!displayGav).with(r -> r.name),
new Column().header("ARTIFACT-ID").visible(displayGav).dataAlign(HorizontalAlign.LEFT)
.with(this::shortGav),
new Column().header("LEVEL").dataAlign(HorizontalAlign.LEFT).with(this::level),
new Column().header("NATIVE").dataAlign(HorizontalAlign.CENTER)
.visible(RuntimeType.quarkus == runtime).with(this::nativeSupported),
new Column().header("SINCE").dataAlign(HorizontalAlign.RIGHT).with(r -> r.since),
new Column().header("DESCRIPTION").dataAlign(HorizontalAlign.LEFT)
.maxWidth(descWidth, OverflowBehaviour.ELLIPSIS_RIGHT)
.with(this::shortDescription))));
.visible(quarkus).with(this::nativeSupported),
CamelTableColumns.since().with(r -> r.since),
CamelTableColumns.lastText("DESCRIPTION", descWidth).with(this::shortDescription))));
}
} else if (filterName != null) {
// suggest similar names when filter returns no results
Expand All @@ -196,10 +198,6 @@ public Integer doCall() throws Exception {
return 0;
}

int nameWidth() {
return 30;
}

int sortRow(Row o1, Row o2) {
String s = sort;
int negate = 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.github.freva.asciitable.HorizontalAlign;
import org.apache.camel.dsl.jbang.core.commands.CamelCommand;
import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
import org.apache.camel.dsl.jbang.core.common.CamelTableColumns;
import org.apache.camel.dsl.jbang.core.common.TerminalWidthHelper;
import org.apache.camel.dsl.jbang.core.common.VersionHelper;
import org.apache.camel.main.download.DependencyDownloaderClassLoader;
Expand Down Expand Up @@ -113,18 +114,17 @@ public Integer doCall() throws Exception {
rows.sort(this::sortRow);

if (!rows.isEmpty()) {
int tw = terminalWidth();
// Fixed columns: NAME (~30), TYPE (10), LEVEL (12)
int fixedWidth = 30 + 10 + 12;
int descWidth = TerminalWidthHelper.flexWidth(
tw, fixedWidth, TerminalWidthHelper.noBorderOverhead(4),
20, 80);
// Size the DESCRIPTION column to fill the terminal from the measured width of the other columns.
int nameW = CamelTableColumns.measure("NAME", CamelTableColumns.NAME_MAX, rows, r -> r.name);
int typeW = Math.max(10, CamelTableColumns.measure("TYPE", Integer.MAX_VALUE, rows, r -> r.type));
int levelW = Math.max(12, CamelTableColumns.measure("LEVEL", Integer.MAX_VALUE, rows, r -> r.supportLevel));
int descWidth = CamelTableColumns.lastColumnWidth(
terminalWidth(), TerminalWidthHelper.noBorderOverhead(4), nameW, typeW, levelW);
printer().println(AsciiTable.getTable(AsciiTable.NO_BORDERS, rows, Arrays.asList(
new Column().header("NAME").dataAlign(HorizontalAlign.LEFT).with(r -> r.name),
CamelTableColumns.name().with(r -> r.name),
new Column().header("TYPE").dataAlign(HorizontalAlign.LEFT).minWidth(10).with(r -> r.type),
new Column().header("LEVEL").dataAlign(HorizontalAlign.LEFT).minWidth(12).with(r -> r.supportLevel),
new Column().header("DESCRIPTION").dataAlign(HorizontalAlign.LEFT).maxWidth(descWidth)
.with(this::getDescription))));
CamelTableColumns.lastText("DESCRIPTION", descWidth).with(this::getDescription))));
}

return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,6 @@ public CatalogTransformer(CamelJBangMain main) {
super(main);
}

@Override
int nameWidth() {
return 60;
}

@Override
List<Row> collectRows() {
List<Row> rows = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import org.apache.camel.catalog.DefaultCamelCatalog;
import org.apache.camel.dsl.jbang.core.commands.CamelCommand;
import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
import org.apache.camel.dsl.jbang.core.common.CamelTableColumns;
import org.apache.camel.dsl.jbang.core.common.CommandLineHelper;
import org.apache.camel.dsl.jbang.core.common.TerminalWidthHelper;
import org.apache.camel.dsl.jbang.core.model.InfraBaseDTO;
Expand Down Expand Up @@ -192,40 +193,54 @@ public int listServices(Consumer<List<Row>> serviceConsumer) throws IOException
if (jsonOutput) {
printer().println(
Jsoner.serialize(
rows.stream().map(row -> {
Object serviceDataObj = null;
try {
serviceDataObj = Jsoner.deserialize(row.serviceData());
} catch (DeserializationException e) {
// ignore
}
return new InfraBaseDTO(row.alias, row.aliasImplementation, row.description, serviceDataObj);
})
rows.stream().map(row -> new InfraBaseDTO(
row.alias, row.aliasImplementation, row.description,
parseServiceData(row.serviceData())))
.map(InfraBaseDTO::toMap)
.collect(Collectors.toList())));
} else {
int tw = terminalWidth();
// Fixed columns: PID (~8), ALIAS (width+2), SERVICE_DATA (~30), DESCRIPTION (~30)
int fixedWidth = (width + 2) + 30 + 30;
if (showPidColumn()) {
fixedWidth += 8;
}
int implWidth = TerminalWidthHelper.flexWidth(
tw, fixedWidth, TerminalWidthHelper.noBorderOverhead(showPidColumn() ? 5 : 4),
20, 35);
// Size DESCRIPTION to fill the terminal: measure the other columns so it gets the exact remainder.
// IMPLEMENTATION is capped and SERVICE_DATA keeps a compact fixed width; both truncate with an ellipsis
// instead of overflowing the terminal (the full, structured service data is available via --json).
int serviceDataWidth = 30;
int aliasWidth = width + 2;
int pidWidth = showPidColumn()
? CamelTableColumns.measure("PID", Integer.MAX_VALUE, rows, r -> r.pid) : 0;
int implWidth = CamelTableColumns.measure("IMPLEMENTATION", 35, rows, Row::aliasImplementation);
int overhead = TerminalWidthHelper.noBorderOverhead(showPidColumn() ? 5 : 4);
int descWidth = CamelTableColumns.lastColumnWidth(
tw, overhead, pidWidth, aliasWidth, implWidth, serviceDataWidth);
printer().println(AsciiTable.getTable(AsciiTable.NO_BORDERS, rows, Arrays.asList(
new Column().header("PID").visible(showPidColumn()).headerAlign(HorizontalAlign.CENTER).with(r -> r.pid),
new Column().header("ALIAS").minWidth(width + 2).dataAlign(HorizontalAlign.LEFT)
new Column().header("ALIAS").minWidth(aliasWidth).dataAlign(HorizontalAlign.LEFT)
.with(Row::alias),
new Column().header("IMPLEMENTATION").maxWidth(implWidth, OverflowBehaviour.NEWLINE)
new Column().header("IMPLEMENTATION").maxWidth(implWidth, OverflowBehaviour.ELLIPSIS_RIGHT)
.dataAlign(HorizontalAlign.LEFT).with(Row::aliasImplementation),
new Column().header("DESCRIPTION").dataAlign(HorizontalAlign.LEFT).with(Row::description),
new Column().header("SERVICE_DATA").dataAlign(HorizontalAlign.LEFT).with(Row::serviceData))));
CamelTableColumns.lastText("DESCRIPTION", descWidth).with(Row::description),
new Column().header("SERVICE_DATA").maxWidth(serviceDataWidth, OverflowBehaviour.ELLIPSIS_RIGHT)
.dataAlign(HorizontalAlign.LEFT).with(Row::serviceData))));
}

return 0;
}

/**
* Parses the raw service-data JSON string (read from the infra {@code .json} file) into a structured object so it
* is emitted as nested JSON by {@code --json}, rather than as an escaped string. Returns {@code null} (so the
* {@code serviceData} field is omitted) when there is no data or the stored content is not valid JSON.
*/
static Object parseServiceData(String serviceData) {
if (serviceData == null) {
return null;
}
try {
return Jsoner.deserialize(serviceData);
} catch (DeserializationException e) {
return null;
}
}

private String getServiceData(String key, String pid) {
Path jsonFilePath = CommandLineHelper.getCamelDir().resolve(getJsonFileName(key, pid));
if (jsonFilePath.toFile().exists()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import com.github.freva.asciitable.HorizontalAlign;
import org.apache.camel.dsl.jbang.core.commands.CamelCommand;
import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
import org.apache.camel.dsl.jbang.core.common.CamelTableColumns;
import org.apache.camel.dsl.jbang.core.common.RuntimeType;
import org.apache.camel.dsl.jbang.core.common.TerminalWidthHelper;
import org.apache.camel.dsl.jbang.core.common.VersionHelper;
Expand Down Expand Up @@ -183,21 +184,23 @@ public Integer doCall() throws Exception {
.map(UpdateListDTO::toMap)
.collect(Collectors.toList())));
} else {
int tw = terminalWidth();
// Fixed columns: VERSION (10), RUNTIME (~18), RUNTIME VERSION (~17)
int fixedWidth = 10 + 18 + 17;
int descWidth = TerminalWidthHelper.flexWidth(
tw, fixedWidth, TerminalWidthHelper.noBorderOverhead(4),
20, 80);
// Size the DESCRIPTION column to fill the terminal: measure the actual rendered width of the
// other columns so the remainder handed to the last column is exact (see CamelTableColumns).
int versionW = CamelTableColumns.measure("VERSION", Integer.MAX_VALUE, rows, r -> r.version().toString());
int runtimeW = CamelTableColumns.measure("RUNTIME", Integer.MAX_VALUE, rows, r -> r.runtime());
int runtimeVersionW
= CamelTableColumns.measure("RUNTIME VERSION", Integer.MAX_VALUE, rows, r -> r.runtimeVersion());
int overhead = TerminalWidthHelper.noBorderOverhead(4);
int descWidth
= CamelTableColumns.lastColumnWidth(terminalWidth(), overhead, versionW, runtimeW, runtimeVersionW);
printer().println(AsciiTable.getTable(AsciiTable.NO_BORDERS, rows, Arrays.asList(
new Column().header("VERSION").minWidth(10).dataAlign(HorizontalAlign.LEFT)
new Column().header("VERSION").dataAlign(HorizontalAlign.LEFT)
.with(r -> r.version().toString()),
new Column().header("RUNTIME")
.dataAlign(HorizontalAlign.LEFT).with(r -> r.runtime()),
new Column().header("RUNTIME VERSION")
.dataAlign(HorizontalAlign.LEFT).with(r -> r.runtimeVersion()),
new Column().header("DESCRIPTION").maxWidth(descWidth)
.dataAlign(HorizontalAlign.LEFT).with(r -> r.description()))));
CamelTableColumns.lastText("DESCRIPTION", descWidth).with(r -> r.description()))));
}

return 0;
Expand Down
Loading