jamesfredley commented on code in PR #15367:
URL: https://github.com/apache/grails-core/pull/15367#discussion_r2748561905

##########
grails-bootstrap/src/main/groovy/grails/build/logging/GrailsConsole.java:
##########
@@ -251,51 +241,50 @@ private boolean readPropOrTrue(String prop) {
         return property == null ? true : Boolean.valueOf(property);
     }
 
-    protected ConsoleReader createConsoleReader(InputStream systemIn) throws 
IOException {
-        // need to swap out the output to avoid logging during init
-        final PrintStream nullOutput = new PrintStream(new 
ByteArrayOutputStream());
-        final PrintStream originalOut = Log.getOutput();
-        try {
-            Log.setOutput(nullOutput);
-            ConsoleReader consoleReader = new ConsoleReader(systemIn, out);
-            consoleReader.setExpandEvents(false);
-            return consoleReader;
-        } finally {
-            Log.setOutput(originalOut);
-        }
+    protected LineReader createLineReader(Terminal terminal) throws 
IOException {
+        LineReader lineReader = LineReaderBuilder.builder()
+                .terminal(terminal)
+                .option(LineReader.Option.DISABLE_EVENT_EXPANSION, true)
+                .build();
+        return lineReader;
     }
 
     /**
-     * Creates the instance of Terminal used directly in GrailsConsole. Note 
that there is also
-     * another terminal instance created implicitly inside of ConsoleReader. 
That instance
-     * is controlled by the jline.terminal system property.
+     * Creates the instance of Terminal used directly in GrailsConsole.
      */
-    protected Terminal createTerminal() {
-        terminal = TerminalFactory.create();
-        if (isWindows()) {
-            terminal.setEchoEnabled(true);
-        }
+    protected Terminal createTerminal() throws IOException {
+        Terminal terminal = TerminalBuilder.builder()
+                .system(true)
+                .build();
         return terminal;
     }
 
     public void resetCompleters() {
-        final ConsoleReader reader = getReader();
-        if (reader != null) {
-            Collection<Completer> completers = reader.getCompleters();
-            for (Completer completer : completers) {
-                reader.removeCompleter(completer);
-            }
+        // In JLine 3, completers are set at LineReader creation time or via 
setCompleter
+        // We'll handle this differently - completers are managed via the 
LineReader
+    }
 
-            // for some unknown reason / bug in JLine you have to iterate over 
twice to clear the completers (WTF)
-            completers = reader.getCompleters();
-            for (Completer completer : completers) {
-                reader.removeCompleter(completer);
+    public void addCompleter(Completer completer) {
+        // In JLine 3, we need to recreate the LineReader with the new 
completer
+        // or use an AggregateCompleter. For now, this is a simplified 
implementation.
+        if (terminal != null) {
+            try {
+                reader = LineReaderBuilder.builder()
+                        .terminal(terminal)
+                        .completer(completer)
+                        .option(LineReader.Option.DISABLE_EVENT_EXPANSION, 
true)
+                        .build();
+                if (history != null) {
+                    reader.setVariable(LineReader.HISTORY_FILE, new 
File(System.getProperty("user.home"), HISTORYFILE).toPath());
+                }

Review Comment:
   Fixed: History is now properly attached via  and the history file path is 
set via .



##########
grails-bootstrap/src/main/groovy/org/grails/build/interactive/CandidateListCompletionHandler.java:
##########
@@ -18,76 +18,62 @@
  */
 package org.grails.build.interactive;
 
-import java.io.IOException;
 import java.util.List;
 
-import jline.console.ConsoleReader;
-import jline.console.CursorBuffer;
-import jline.console.completer.CompletionHandler;
+import org.jline.reader.Candidate;
+import org.jline.reader.Completer;
+import org.jline.reader.LineReader;
+import org.jline.reader.ParsedLine;
 
 /**
- * Fixes issues with the default CandidateListCompletionHandler such as 
clearing out the whole buffer when
- * a completion matches a list of candidates
+ * A Completer implementation that wraps candidate list completion behavior.
+ * In JLine 3, completion handling is integrated into the LineReader itself,
+ * so this class now acts as a utility completer that can be composed with 
others.
  *
  * @author Graeme Rocher
  * @since 2.0
  */
-public class CandidateListCompletionHandler implements CompletionHandler {
+public class CandidateListCompletionHandler implements Completer {
 
+    private final Completer delegate;
     private boolean eagerNewlines = true;
 
-    public void setAlwaysIncludeNewline(boolean eagerNewlines) {
-        this.eagerNewlines = eagerNewlines;
+    public CandidateListCompletionHandler() {
+        this.delegate = null;
     }
 
-    public boolean complete(ConsoleReader reader, 
@SuppressWarnings("rawtypes") List<CharSequence> candidates, int pos) throws 
IOException {
-        CursorBuffer buf = reader.getCursorBuffer();
-
-        // if there is only one completion, then fill in the buffer
-        if (candidates.size() == 1) {
-            String value = candidates.get(0).toString();
-
-            // fail if the only candidate is the same as the current buffer
-            if (value.equals(buf.toString())) {
-                return false;
-            }
-
-            
jline.console.completer.CandidateListCompletionHandler.setBuffer(reader, value, 
pos);
-
-            return true;
-        }
-
-        if (candidates.size() > 1) {
-            String value = getUnambiguousCompletions(candidates);
+    public CandidateListCompletionHandler(Completer delegate) {
+        this.delegate = delegate;
+    }
 
-            
jline.console.completer.CandidateListCompletionHandler.setBuffer(reader, value, 
pos);
-        }
+    public void setAlwaysIncludeNewline(boolean eagerNewlines) {
+        this.eagerNewlines = eagerNewlines;
+    }

Review Comment:
   Fixed: Removed the unused eagerNewlines field and setAlwaysIncludeNewline 
method.



##########
grails-shell-cli/src/main/groovy/org/grails/cli/profile/commands/CreateAppCommand.groovy:
##########
@@ -119,37 +119,37 @@ class CreateAppCommand extends ArgumentCompletingCommand 
implements ProfileRepos
                     }.collect() { String pn ->
                         "${pn.substring(valStr.size())} ".toString()
                     }
-                    candidates.addAll(candidateProfiles)
-                    return cursor
+                    candidateProfiles.each { candidates.add(new 
org.jline.reader.Candidate(it)) }
+                    return
                 }
             } else if (lastOption.key == FEATURES_FLAG) {
                 def val = lastOption.value
                 def profile = 
profileRepository.getProfile(commandLine.hasOption(PROFILE_FLAG) ? 
commandLine.optionValue(PROFILE_FLAG).toString() : getDefaultProfile())
                 def featureNames = profile.features.collect() { Feature f -> 
f.name }
                 if (val == true) {
-                    candidates.addAll(featureNames)
-                    return cursor
+                    featureNames.each { candidates.add(new 
org.jline.reader.Candidate(it)) }
+                    return
                 } else if (!profileNames.contains(val)) {
                     def valStr = val.toString()
                     if (valStr.endsWith(',')) {
                         def specified = valStr.split(',')
-                        candidates.addAll(featureNames.findAll { String f ->
+                        featureNames.findAll { String f ->
                             !specified.contains(f)
-                        })
-                        return cursor
+                        }.each { candidates.add(new 
org.jline.reader.Candidate(it)) }
+                        return
                     }
 
                     def candidatesFeatures = featureNames.findAll { String pn 
->
                         pn.startsWith(valStr)
                     }.collect() { String pn ->
                         "${pn.substring(valStr.size())} ".toString()
                     }
-                    candidates.addAll(candidatesFeatures)
-                    return cursor
+                    candidatesFeatures.each { candidates.add(new 
org.jline.reader.Candidate(it)) }
+                    return

Review Comment:
   Fixed: Completion candidates now use the full feature/profile name instead 
of just the suffix.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to