diff --git a/console-ui/src/main/java/org/jline/consoleui/elements/Text.java b/console-ui/src/main/java/org/jline/consoleui/elements/Text.java new file mode 100644 index 000000000..8eebee6e5 --- /dev/null +++ b/console-ui/src/main/java/org/jline/consoleui/elements/Text.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2024, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package org.jline.consoleui.elements; + +import java.util.List; + +import org.jline.utils.AttributedString; + +public class Text extends AbstractPromptableElement { + private final List lines; + + private static int num = 0; + + public Text(List lines) { + // We don't actually care about names, so we just generate a unique one + super("", "_text_" + ++num); + this.lines = lines; + } + + public List getLines() { + return lines; + } +} diff --git a/console-ui/src/main/java/org/jline/consoleui/prompt/AbstractPrompt.java b/console-ui/src/main/java/org/jline/consoleui/prompt/AbstractPrompt.java index da9e4853a..91d46d9c1 100644 --- a/console-ui/src/main/java/org/jline/consoleui/prompt/AbstractPrompt.java +++ b/console-ui/src/main/java/org/jline/consoleui/prompt/AbstractPrompt.java @@ -15,10 +15,7 @@ import org.jline.consoleui.elements.ConfirmChoice; import org.jline.consoleui.elements.ExpandableChoice; import org.jline.consoleui.elements.InputValue; -import org.jline.consoleui.elements.items.CheckboxItemIF; -import org.jline.consoleui.elements.items.ChoiceItemIF; -import org.jline.consoleui.elements.items.ConsoleUIItemIF; -import org.jline.consoleui.elements.items.ListItemIF; +import org.jline.consoleui.elements.items.*; import org.jline.consoleui.elements.items.impl.CheckboxItem; import org.jline.consoleui.elements.items.impl.ChoiceItem; import org.jline.consoleui.elements.items.impl.Separator; diff --git a/console-ui/src/main/java/org/jline/consoleui/prompt/ConsolePrompt.java b/console-ui/src/main/java/org/jline/consoleui/prompt/ConsolePrompt.java index 0ebcf07f6..dace16a1a 100644 --- a/console-ui/src/main/java/org/jline/consoleui/prompt/ConsolePrompt.java +++ b/console-ui/src/main/java/org/jline/consoleui/prompt/ConsolePrompt.java @@ -252,16 +252,21 @@ public void prompt( } this.header = headerIn; + boolean backward = false; for (int i = resultMap.isEmpty() ? 0 : resultMap.size() - 1; i < promptableElementList.size(); i++) { PromptableElementIF pe = promptableElementList.get(i); - PromptResultItemIF result = promptElement(header, pe); + if (backward) { + removePreviousResult(pe); + backward = false; + } + PromptResultItemIF oldResult = resultMap.get(pe.getName()); + PromptResultItemIF result = promptElement(header, pe, oldResult); if (result == null) { // Prompt was cancelled by the user if (i > 0) { - // Remove last result - header.remove(header.size() - 1); // Go back to previous prompt i -= 2; + backward = true; continue; } else { if (config.cancellableFirstPrompt()) { @@ -274,22 +279,40 @@ public void prompt( } } } - String resp = result.getDisplayResult(); - if (result instanceof ConfirmResult) { - ConfirmResult cr = (ConfirmResult) result; - if (cr.getConfirmed() == ConfirmChoice.ConfirmationValue.YES) { - resp = config.resourceBundle().getString("confirmation_yes_answer"); - } else { - resp = config.resourceBundle().getString("confirmation_no_answer"); + AttributedStringBuilder message; + if (pe instanceof Text) { + Text te = (Text) pe; + header.addAll(te.getLines()); + } else { + String resp = result.getDisplayResult(); + if (result instanceof ConfirmResult) { + ConfirmResult cr = (ConfirmResult) result; + if (cr.getConfirmed() == ConfirmChoice.ConfirmationValue.YES) { + resp = config.resourceBundle().getString("confirmation_yes_answer"); + } else { + resp = config.resourceBundle().getString("confirmation_no_answer"); + } } + message = createMessage(pe.getMessage(), resp); + header.add(message.toAttributedString()); } - AttributedStringBuilder message = createMessage(pe.getMessage(), resp); - header.add(message.toAttributedString()); resultMap.put(pe.getName(), result); } } - protected PromptResultItemIF promptElement(List header, PromptableElementIF pe) { + private void removePreviousResult(PromptableElementIF pe) { + if (pe instanceof Text) { + Text te = (Text) pe; + for (int i = 0; i < te.getLines().size(); i++) { + header.remove(header.size() - 1); + } + } else { + header.remove(header.size() - 1); + } + } + + protected PromptResultItemIF promptElement( + List header, PromptableElementIF pe, PromptResultItemIF oldResult) { AttributedStringBuilder message = createMessage(pe.getMessage(), null); AttributedStringBuilder asb = new AttributedStringBuilder(); asb.append(message); @@ -354,6 +377,9 @@ protected PromptResultItemIF promptElement(List header, Prompt asb.append(" "); result = ConfirmPrompt.getPrompt(terminal, header, asb.toAttributedString(), cc, config) .execute(); + } else if (pe instanceof Text) { + Text te = (Text) pe; + result = oldResult == null ? NoResult.INSTANCE : null; } else { throw new IllegalArgumentException("wrong type of promptable element"); } diff --git a/console-ui/src/main/java/org/jline/consoleui/prompt/NoResult.java b/console-ui/src/main/java/org/jline/consoleui/prompt/NoResult.java new file mode 100644 index 000000000..cbcc323d5 --- /dev/null +++ b/console-ui/src/main/java/org/jline/consoleui/prompt/NoResult.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2024, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package org.jline.consoleui.prompt; + +public class NoResult implements PromptResultItemIF { + + public static final NoResult INSTANCE = new NoResult(); + + private NoResult() {} + + public String getDisplayResult() { + return ""; + } + + public String getResult() { + return ""; + } + + @Override + public String toString() { + return "NoResult{}"; + } +} diff --git a/console-ui/src/main/java/org/jline/consoleui/prompt/builder/PromptBuilder.java b/console-ui/src/main/java/org/jline/consoleui/prompt/builder/PromptBuilder.java index 4d3b2e555..6178f8503 100644 --- a/console-ui/src/main/java/org/jline/consoleui/prompt/builder/PromptBuilder.java +++ b/console-ui/src/main/java/org/jline/consoleui/prompt/builder/PromptBuilder.java @@ -46,4 +46,8 @@ public CheckboxPromptBuilder createCheckboxPrompt() { public ConfirmPromptBuilder createConfirmPromp() { return new ConfirmPromptBuilder(this); } + + public TextBuilder createText() { + return new TextBuilder(this); + } } diff --git a/console-ui/src/main/java/org/jline/consoleui/prompt/builder/TextBuilder.java b/console-ui/src/main/java/org/jline/consoleui/prompt/builder/TextBuilder.java new file mode 100644 index 000000000..a1ff63d99 --- /dev/null +++ b/console-ui/src/main/java/org/jline/consoleui/prompt/builder/TextBuilder.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2024, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package org.jline.consoleui.prompt.builder; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.jline.consoleui.elements.Text; +import org.jline.utils.AttributedString; +import org.jline.utils.AttributedStringBuilder; +import org.jline.utils.AttributedStyle; + +public class TextBuilder { + private final PromptBuilder promptBuilder; + private final List lines = new ArrayList<>(); + + public TextBuilder(PromptBuilder promptBuilder) { + this.promptBuilder = promptBuilder; + } + + public TextBuilder addLine(AttributedString text) { + lines.add(text); + return this; + } + + public TextBuilder addLine(String line) { + lines.add(new AttributedString(line)); + return this; + } + + public TextBuilder addLine(AttributedStyle style, String line) { + AttributedStringBuilder asb = new AttributedStringBuilder(); + asb.append(line, style); + lines.add(asb.toAttributedString()); + return this; + } + + public TextBuilder addLines(AttributedString... lines) { + this.lines.addAll(Arrays.asList(lines)); + return this; + } + + public TextBuilder addLines(String... lines) { + for (String s : lines) { + this.lines.add(new AttributedString(s)); + } + return this; + } + + public TextBuilder addLines(AttributedStyle style, String... lines) { + for (String s : lines) { + AttributedStringBuilder asb = new AttributedStringBuilder(); + asb.append(s, style); + this.lines.add(asb.toAttributedString()); + } + return this; + } + + public PromptBuilder addPrompt() { + Text text = new Text(lines); + promptBuilder.addPrompt(text); + return promptBuilder; + } +} diff --git a/console-ui/src/test/java/org/jline/consoleui/examples/BasicDynamic.java b/console-ui/src/test/java/org/jline/consoleui/examples/BasicDynamic.java index 5d82ffbd0..2c5ee8615 100644 --- a/console-ui/src/test/java/org/jline/consoleui/examples/BasicDynamic.java +++ b/console-ui/src/test/java/org/jline/consoleui/examples/BasicDynamic.java @@ -30,6 +30,9 @@ import org.jline.utils.OSUtils; public class BasicDynamic { + private static final AttributedStyle ITALIC_GREEN = + AttributedStyle.DEFAULT.italic().foreground(2); + private static final AttributedStyle BOLD_RED = AttributedStyle.BOLD.foreground(1); private static void addInHeader(List header, String text) { addInHeader(header, AttributedStyle.DEFAULT, text); @@ -43,8 +46,7 @@ private static void addInHeader(List header, AttributedStyle s public static void main(String[] args) { List header = new ArrayList<>(); - AttributedStyle style = new AttributedStyle(); - addInHeader(header, style.italic().foreground(2), "Hello Dynamic World!"); + addInHeader(header, ITALIC_GREEN, "Hello Dynamic World!"); addInHeader( header, "This is a demonstration of ConsoleUI java library. It provides a simple console interface"); addInHeader( @@ -141,6 +143,7 @@ static List pizzaOrHamburgerPrompt(ConsolePrompt prompt) { static List pizzaPrompt(ConsolePrompt prompt) { PromptBuilder promptBuilder = prompt.getPromptBuilder(); + promptBuilder.createText().addLine(ITALIC_GREEN, "Pizza time!").addPrompt(); promptBuilder .createListPrompt() .name("pizzatype") @@ -197,6 +200,7 @@ static List pizzaPrompt(ConsolePrompt prompt) { static List hamburgerPrompt(ConsolePrompt prompt) { PromptBuilder promptBuilder = prompt.getPromptBuilder(); + promptBuilder.createText().addLine(ITALIC_GREEN, "Hamburger time!").addPrompt(); promptBuilder .createListPrompt() .name("hamburgertype") @@ -241,6 +245,12 @@ static List hamburgerPrompt(ConsolePrompt prompt) { static List finalPrompt(ConsolePrompt prompt) { PromptBuilder promptBuilder = prompt.getPromptBuilder(); + promptBuilder + .createText() + .addLine(BOLD_RED, "###################") + .addLine(ITALIC_GREEN, "Finalize your order") + .addLine(BOLD_RED, "###################") + .addPrompt(); promptBuilder .createChoicePrompt() .name("payment")