1919package grails.boot
2020
2121import groovy.transform.CompileStatic
22+ import groovy.transform.Immutable
2223
2324import org.springframework.boot.Banner
2425import org.springframework.boot.SpringBootVersion
@@ -36,8 +37,6 @@ class GrailsBanner implements Banner {
3637 String bannerFile = ' grails-banner.txt'
3738 int upperPadding = 1
3839 int lowerPadding = 1
39- int versionsMargin = 4
40- String versionsSeparator = ' | '
4140
4241 @Override
4342 void printBanner (Environment environment , Class<?> sourceClass , PrintStream out ) {
@@ -53,7 +52,7 @@ class GrailsBanner implements Banner {
5352 }
5453
5554 if (shouldDisplayVersions(environment)) {
56- buildVersionRows (createBannerVersions(environment), bannerWidth)
55+ createVersionsFormatter() . format (createBannerVersions(environment), bannerWidth)
5756 .forEach { out. println (it) }
5857 }
5958
@@ -84,32 +83,69 @@ class GrailsBanner implements Banner {
8483 environment. getProperty(' grails.banner.display.versions' , Boolean , true )
8584 }
8685
87- protected List buildVersionRows (Map versions , int bannerWidth ) {
88- def maxWidth = bannerWidth - versionsMargin * 2
89- def rows = []
90- def currentRow = new StringBuilder ()
91- def countInRow = 0
92- versions. each {
93- String value = " $it . key : $it . value "
94- def proposedLength = currentRow. size() + (countInRow > 0 ? versionsSeparator. size() : 0 ) + value. size()
95- def wouldOverflow = proposedLength > maxWidth
96- if (wouldOverflow) {
97- rows << currentRow. center(bannerWidth)
98- currentRow. length = 0
86+ protected VersionsFormatter createVersionsFormatter () {
87+ new DefaultVersionFormatter ()
88+ }
89+
90+ private static int longestLineLength (String text ) {
91+ text. readLines()* . size()?. max() ?: 0
92+ }
93+
94+ @FunctionalInterface
95+ interface VersionsFormatter {
96+
97+ /**
98+ * @param versions insertion-ordered map (e.g., LinkedHashMap) of label -> value
99+ * @param bannerWidth total banner width in characters
100+ * @return formatted lines to print
101+ */
102+ List<String > format (Map<String , ?> versions , int bannerWidth )
103+ }
104+
105+ @CompileStatic
106+ class DefaultVersionFormatter implements VersionsFormatter {
107+
108+ VersionsFormatOptions options = new VersionsFormatOptions ()
109+
110+ @Override
111+ List<String > format (Map<String , ?> versions , int bannerWidth ) {
112+ def columnWidth = bannerWidth - options. margin * 2
113+ List<String > rows = []
114+ def currentRow = new StringBuilder ()
115+ def countInRow = 0
116+
117+ versions. each { k , v ->
118+ String item = " $k : $v "
119+ def proposedLength = currentRow. length() + (countInRow > 0 ? options. separator. size() : 0 ) + item. size()
120+ def wouldOverflow = (countInRow > 0 && proposedLength > columnWidth)
121+ def hitCountLimit = (options. maxItemsPerRow > 0 && countInRow >= options. maxItemsPerRow)
122+
123+ if (wouldOverflow || hitCountLimit) {
124+ rows << currentRow. center(bannerWidth)
125+ currentRow. length = 0
126+ countInRow = 0
127+ }
128+
129+ if (currentRow. size() > 0 ) {
130+ currentRow << options. separator
131+ }
132+ currentRow << item
133+ countInRow++
99134 }
100- if (currentRow. size() > 0 ) {
101- currentRow << versionsSeparator
135+
136+ if (countInRow > 0 ) {
137+ rows << currentRow. center(bannerWidth)
102138 }
103- currentRow << value
104- countInRow++
105- }
106- if (countInRow > 0 ) {
107- rows << currentRow. center(bannerWidth)
139+
140+ return rows
108141 }
109- rows
110142 }
111143
112- private static int longestLineLength (String text ) {
113- text. readLines()* . size()?. max() ?: 0
144+ @Immutable
145+ @CompileStatic
146+ class VersionsFormatOptions {
147+ int margin = 4
148+ int maxItemsPerRow = 0 // 0 or negative = unlimited
149+ String separator = ' | '
114150 }
115151}
0 commit comments