langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java
changeset 41865 3ef02797070d
parent 41631 a348d1cc8d9d
child 41934 a4da50688dc7
equal deleted inserted replaced
41864:f7dbab23003a 41865:3ef02797070d
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package jdk.internal.jshell.tool;
    26 package jdk.internal.jshell.tool;
    27 
    27 
       
    28 import jdk.jshell.SourceCodeAnalysis.Documentation;
    28 import jdk.jshell.SourceCodeAnalysis.QualifiedNames;
    29 import jdk.jshell.SourceCodeAnalysis.QualifiedNames;
    29 import jdk.jshell.SourceCodeAnalysis.Suggestion;
    30 import jdk.jshell.SourceCodeAnalysis.Suggestion;
    30 
    31 
    31 import java.awt.event.ActionListener;
    32 import java.awt.event.ActionListener;
    32 import java.io.IOException;
    33 import java.io.IOException;
    33 import java.io.InputStream;
    34 import java.io.InputStream;
    34 import java.io.InterruptedIOException;
    35 import java.io.InterruptedIOException;
    35 import java.io.PrintStream;
    36 import java.io.PrintStream;
    36 import java.io.UncheckedIOException;
    37 import java.io.UncheckedIOException;
    37 import java.lang.reflect.Method;
       
    38 import java.util.ArrayList;
    38 import java.util.ArrayList;
       
    39 import java.util.Arrays;
    39 import java.util.Collection;
    40 import java.util.Collection;
    40 import java.util.Collections;
    41 import java.util.Collections;
    41 import java.util.HashMap;
    42 import java.util.HashMap;
       
    43 import java.util.Iterator;
    42 import java.util.List;
    44 import java.util.List;
    43 import java.util.Locale;
    45 import java.util.Locale;
    44 import java.util.Map;
    46 import java.util.Map;
    45 import java.util.Objects;
    47 import java.util.Objects;
    46 import java.util.Optional;
    48 import java.util.Optional;
    47 import java.util.function.Supplier;
    49 import java.util.function.Function;
    48 import java.util.prefs.BackingStoreException;
    50 import java.util.prefs.BackingStoreException;
    49 import java.util.stream.Collectors;
    51 import java.util.stream.Collectors;
    50 import java.util.stream.Stream;
    52 import java.util.stream.Stream;
    51 
    53 
       
    54 import jdk.internal.shellsupport.doc.JavadocFormatter;
    52 import jdk.internal.jline.NoInterruptUnixTerminal;
    55 import jdk.internal.jline.NoInterruptUnixTerminal;
    53 import jdk.internal.jline.Terminal;
    56 import jdk.internal.jline.Terminal;
    54 import jdk.internal.jline.TerminalFactory;
    57 import jdk.internal.jline.TerminalFactory;
    55 import jdk.internal.jline.TerminalSupport;
    58 import jdk.internal.jline.TerminalSupport;
    56 import jdk.internal.jline.WindowsTerminal;
    59 import jdk.internal.jline.WindowsTerminal;
    57 import jdk.internal.jline.console.ConsoleReader;
    60 import jdk.internal.jline.console.ConsoleReader;
       
    61 import jdk.internal.jline.console.CursorBuffer;
    58 import jdk.internal.jline.console.KeyMap;
    62 import jdk.internal.jline.console.KeyMap;
    59 import jdk.internal.jline.console.UserInterruptException;
    63 import jdk.internal.jline.console.UserInterruptException;
    60 import jdk.internal.jline.console.completer.Completer;
    64 import jdk.internal.jline.console.completer.Completer;
    61 import jdk.internal.jline.console.history.History;
    65 import jdk.internal.jline.console.history.History;
    62 import jdk.internal.jline.console.history.MemoryHistory;
    66 import jdk.internal.jline.console.history.MemoryHistory;
   257         "\033\012", //Alt-Enter (Linux)
   261         "\033\012", //Alt-Enter (Linux)
   258         "\033\133\061\067\176", //F6/Alt-F1 (Mac)
   262         "\033\133\061\067\176", //F6/Alt-F1 (Mac)
   259         "\u001BO3P" //Alt-F1 (Linux)
   263         "\u001BO3P" //Alt-F1 (Linux)
   260     };
   264     };
   261 
   265 
       
   266     private String lastDocumentationBuffer;
       
   267     private int lastDocumentationCursor = (-1);
       
   268 
   262     private void documentation(JShellTool repl) {
   269     private void documentation(JShellTool repl) {
   263         String buffer = in.getCursorBuffer().buffer.toString();
   270         String buffer = in.getCursorBuffer().buffer.toString();
   264         int cursor = in.getCursorBuffer().cursor;
   271         int cursor = in.getCursorBuffer().cursor;
   265         String doc;
   272         boolean firstInvocation = !buffer.equals(lastDocumentationBuffer) || cursor != lastDocumentationCursor;
       
   273         lastDocumentationBuffer = buffer;
       
   274         lastDocumentationCursor = cursor;
       
   275         List<String> doc;
       
   276         String seeMore;
       
   277         Terminal term = in.getTerminal();
   266         if (prefix.isEmpty() && buffer.trim().startsWith("/")) {
   278         if (prefix.isEmpty() && buffer.trim().startsWith("/")) {
   267             doc = repl.commandDocumentation(buffer, cursor);
   279             doc = Arrays.asList(repl.commandDocumentation(buffer, cursor, firstInvocation));
       
   280             seeMore = "jshell.console.see.help";
   268         } else {
   281         } else {
   269             doc = repl.analysis.documentation(prefix + buffer, cursor + prefix.length());
   282             JavadocFormatter formatter = new JavadocFormatter(term.getWidth(),
       
   283                                                               term.isAnsiSupported());
       
   284             Function<Documentation, String> convertor;
       
   285             if (firstInvocation) {
       
   286                 convertor = d -> d.signature();
       
   287             } else {
       
   288                 convertor = d -> formatter.formatJavadoc(d.signature(),
       
   289                                                          d.javadoc() != null ? d.javadoc()
       
   290                                                                              : repl.messageFormat("jshell.console.no.javadoc"));
       
   291             }
       
   292             doc = repl.analysis.documentation(prefix + buffer, cursor + prefix.length(), !firstInvocation)
       
   293                                .stream()
       
   294                                .map(convertor)
       
   295                                .collect(Collectors.toList());
       
   296             seeMore = "jshell.console.see.javadoc";
   270         }
   297         }
   271 
   298 
   272         try {
   299         try {
   273             if (doc != null) {
   300             if (doc != null && !doc.isEmpty()) {
   274                 in.println();
   301                 if (firstInvocation) {
   275                 in.println(doc);
   302                     in.println();
   276                 in.redrawLine();
   303                     in.println(doc.stream().collect(Collectors.joining("\n")));
   277                 in.flush();
   304                     in.println(repl.messageFormat(seeMore));
       
   305                     in.redrawLine();
       
   306                     in.flush();
       
   307                 } else {
       
   308                     in.println();
       
   309 
       
   310                     int height = term.getHeight();
       
   311                     String lastNote = "";
       
   312 
       
   313                     PRINT_DOC: for (Iterator<String> docIt = doc.iterator(); docIt.hasNext(); ) {
       
   314                         String currentDoc = docIt.next();
       
   315                         String[] lines = currentDoc.split("\n");
       
   316                         int firstLine = 0;
       
   317 
       
   318                         PRINT_PAGE: while (true) {
       
   319                             int toPrint = height - 1;
       
   320 
       
   321                             while (toPrint > 0 && firstLine < lines.length) {
       
   322                                 in.println(lines[firstLine++]);
       
   323                                 toPrint--;
       
   324                             }
       
   325 
       
   326                             if (firstLine >= lines.length) {
       
   327                                 break;
       
   328                             }
       
   329 
       
   330                             lastNote = repl.getResourceString("jshell.console.see.next.page");
       
   331                             in.print(lastNote + ConsoleReader.RESET_LINE);
       
   332                             in.flush();
       
   333 
       
   334                             while (true) {
       
   335                                 int r = in.readCharacter();
       
   336 
       
   337                                 switch (r) {
       
   338                                     case ' ': continue PRINT_PAGE;
       
   339                                     case 'q':
       
   340                                     case 3:
       
   341                                         break PRINT_DOC;
       
   342                                     default:
       
   343                                         in.beep();
       
   344                                         break;
       
   345                                 }
       
   346                             }
       
   347                         }
       
   348 
       
   349                         if (docIt.hasNext()) {
       
   350                             lastNote = repl.getResourceString("jshell.console.see.next.javadoc");
       
   351                             in.print(lastNote + ConsoleReader.RESET_LINE);
       
   352                             in.flush();
       
   353 
       
   354                             while (true) {
       
   355                                 int r = in.readCharacter();
       
   356 
       
   357                                 switch (r) {
       
   358                                     case ' ': continue PRINT_DOC;
       
   359                                     case 'q':
       
   360                                     case 3:
       
   361                                         break PRINT_DOC;
       
   362                                     default:
       
   363                                         in.beep();
       
   364                                         break;
       
   365                                 }
       
   366                             }
       
   367                         }
       
   368                     }
       
   369                     //clear the "press space" line:
       
   370                     in.getCursorBuffer().buffer.replace(0, buffer.length(), lastNote);
       
   371                     in.getCursorBuffer().cursor = 0;
       
   372                     in.killLine();
       
   373                     in.getCursorBuffer().buffer.append(buffer);
       
   374                     in.getCursorBuffer().cursor = cursor;
       
   375                     in.redrawLine();
       
   376                     in.flush();
       
   377                 }
   278             } else {
   378             } else {
   279                 in.beep();
   379                 in.beep();
   280             }
   380             }
   281         } catch (IOException ex) {
   381         } catch (IOException ex) {
   282             throw new IllegalStateException(ex);
   382             throw new IllegalStateException(ex);