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 writer.print(response.getText()); 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 }