001 package org.crsh.processor.jline;
002
003 import jline.console.ConsoleReader;
004 import jline.console.completer.Completer;
005 import org.crsh.cmdline.CommandCompletion;
006 import org.crsh.cmdline.Delimiter;
007 import org.crsh.cmdline.spi.ValueCompletion;
008 import org.crsh.shell.Shell;
009 import org.crsh.shell.ShellProcess;
010 import org.crsh.shell.ShellResponse;
011
012 import java.io.IOException;
013 import java.io.PrintWriter;
014 import java.util.List;
015 import java.util.Map;
016 import java.util.concurrent.atomic.AtomicReference;
017
018 /** @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */
019 public class JLineProcessor implements Runnable, Completer {
020
021 /** . */
022 private final Shell shell;
023
024 /** . */
025 final ConsoleReader reader;
026
027 /** . */
028 final PrintWriter writer;
029
030 /** . */
031 final AtomicReference<ShellProcess> current;
032
033 public JLineProcessor(Shell shell, ConsoleReader reader, PrintWriter writer) {
034 this.shell = shell;
035 this.reader = reader;
036 this.writer = writer;
037 this.current = new AtomicReference<ShellProcess>();
038 }
039
040 public void run() {
041
042 //
043 String welcome = shell.getWelcome();
044 writer.println(welcome);
045 writer.flush();
046
047 //
048 while (true) {
049 String prompt = getPrompt();
050 String line;
051 try {
052 writer.println();
053 writer.flush();
054 if ((line = reader.readLine(prompt)) == null) {
055 break;
056 }
057 }
058 catch (IOException e) {
059 // What should we do other than that ?
060 break;
061 }
062
063 //
064 ShellProcess process = shell.createProcess(line);
065 JLineProcessContext context = new JLineProcessContext(this);
066 current.set(process);
067 try {
068 process.execute(context);
069 try {
070 context.latch.await();
071 }
072 catch (InterruptedException ignore) {
073 // At the moment
074 }
075 }
076 finally {
077 current.set(null);
078 }
079 ShellResponse response = context.resp.get();
080
081 //
082 if (response instanceof ShellResponse.Cancelled) {
083 // Do nothing
084 } else if (response instanceof ShellResponse.Close) {
085 break;
086 } else {
087 response.getReader().writeAnsiTo(writer);
088 writer.flush();
089 }
090 }
091 }
092
093 public int complete(String buffer, int cursor, List<CharSequence> candidates) {
094 String prefix = buffer.substring(0, cursor);
095 CommandCompletion completion = shell.complete(prefix);
096 ValueCompletion vc = completion.getValue();
097 if (vc.isEmpty()) {
098 return -1;
099 }
100 Delimiter delimiter = completion.getDelimiter();
101 for (Map.Entry<String, Boolean> entry : vc) {
102 StringBuilder sb = new StringBuilder();
103 sb.append(vc.getPrefix());
104 try {
105 delimiter.escape(entry.getKey(), sb);
106 if (entry.getValue()) {
107 sb.append(completion.getDelimiter().getValue());
108 }
109 candidates.add(sb.toString());
110 }
111 catch (IOException ignore) {
112 }
113 }
114 return cursor - vc.getPrefix().length();
115 }
116
117 public void cancel() {
118 ShellProcess process = current.get();
119 if (process != null) {
120 process.cancel();
121 } else {
122 writer.println();
123 writer.print(getPrompt());
124 writer.flush();
125 }
126 }
127
128 String getPrompt() {
129 String prompt = shell.getPrompt();
130 return prompt == null ? "% " : prompt;
131 }
132 }