Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion cliche-shell-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@
<artifactId>commons-beanutils-core</artifactId>
<version>1.8.3</version>
</dependency>

<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
</dependency>

</dependencies>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ public List<String> getCommandsNames(String prefix) {

public void addMethod(Method method, Object handler, String prefix) {
Command annotation = method.getAnnotation(Command.class);
assert method != null;
String name;
String autoAbbrev = null;

Expand Down
294 changes: 33 additions & 261 deletions cliche-shell-core/src/main/java/com/maxifier/cliche/ConsoleIO.java
Original file line number Diff line number Diff line change
@@ -1,270 +1,42 @@
/*
* This file is part of the Cliche project, licensed under MIT License.
* See LICENSE.txt file in root folder of Cliche sources.
*/

package com.maxifier.cliche;

import com.maxifier.cliche.util.Strings;

import jline.console.ConsoleReader;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import javax.annotation.Nullable;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.List;

/**
* Console IO subsystem.
* This is also one of special command handlers and is responsible
* for logging (duplicating output) and execution of scripts.
* ConsoleIO
*
* @author ASG
* @author aleksey.didik@maxifier.com (Aleksey Didik) (2013-07-17 13:32)
*/
public class ConsoleIO implements Input, Output, ShellManageable {

public ConsoleIO(ConsoleReader in, PrintStream out, PrintStream err) {
this.in = in;
this.out = out;
this.err = err;
}

public ConsoleIO() throws IOException {
this(new ConsoleReader(System.in, System.out),
System.out, System.err);
}

private ConsoleReader in;
private PrintStream out;
private PrintStream err;

private int lastCommandOffset = 0;

public String readCommand(List<String> path) {
try {
String prompt = Strings.joinStrings(path, false, '/');
switch (inputState) {
case USER:
return readUsersCommand(prompt);
case SCRIPT:
String command = readCommandFromScript(prompt);
if (command != null) {
return command;
} else {
closeScript();
return readUsersCommand(prompt);
}
}
return readUsersCommand(prompt);
} catch (IOException ex) {
throw new Error(ex);
}
}

private static final String USER_PROMPT_SUFFIX = "> ";
private static final String FILE_PROMPT_SUFFIX = "$ ";

private static enum InputState { USER, SCRIPT }

private InputState inputState = InputState.USER;

private String readUsersCommand(String prompt) throws IOException {
String completePrompt = prompt+ USER_PROMPT_SUFFIX;
//print(completePrompt);
lastCommandOffset = completePrompt.length();

String command = in.readLine(completePrompt);
if (log != null) {
log.println(command);
}
return command;
}

private BufferedReader scriptReader = null;

private String readCommandFromScript(String prompt) throws IOException {
String command = scriptReader.readLine();
if (command != null) {
String completePrompt = prompt+ FILE_PROMPT_SUFFIX;
print(completePrompt);
lastCommandOffset = completePrompt.length();
}
return command;
}

private void closeScript() throws IOException {
if (scriptReader != null) {
scriptReader.close();
scriptReader = null;
}
inputState = InputState.USER;
}

@Command(description="Reads commands from file")
public void runScript(
@Param(name="filename", description="Full file name of the script")
String filename
) throws FileNotFoundException {

scriptReader = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
inputState = InputState.SCRIPT;
}


public void outputHeader(String text) {
if (text != null) {
println(text);
}
}

public void output(Object obj, OutputConversionEngine oce) {
if (obj == null) {
return;
} else {
obj = oce.convertOutput(obj);
}

if (obj.getClass().isArray()) {
int length = Array.getLength(obj);
for (int i = 0; i < length; i++) {
output(Array.get(obj, i), 0, oce);
}
} else if (obj instanceof Collection) {
for (Object elem : (Collection)obj) {
output(elem, 0, oce);
}
} else {
output(obj, 0, oce);
}
}

private void output(Object obj, int indent, OutputConversionEngine oce) {
if (obj == null) {
return;
}

if (obj != null) {
obj = oce.convertOutput(obj);
}

for (int i = 0; i < indent; i++) {
print("\t");
}

if (obj == null) {
println("(null)");
} else if (obj.getClass().isPrimitive() || obj instanceof String) {
println(obj);
} else if (obj.getClass().isArray()) {
println("Array");
int length = Array.getLength(obj);
for (int i = 0; i < length; i++) {
output(Array.get(obj, i), indent + 1, oce);
}
} else if (obj instanceof Collection) {
println("Collection");
for (Object elem : (Collection)obj) {
output(elem, indent + 1, oce);
}
} else if (obj instanceof Throwable) {
println(obj); // class and its message
((Throwable)obj).printStackTrace(out);
} else {
println(obj);
}
}

private void print(Object x) {
out.print(x);
if (log != null) {
log.print(x);
}
}

private void println(Object x) {
out.println(x);
if (log != null) {
log.println(x);
}
}

private void printErr(Object x) {
err.print(x);
if (log != null) {
log.print(x);
}
}

private void printlnErr(Object x) {
err.println(x);
if (log != null) {
log.println(x);
}
}

public void outputException(String input, TokenException error) {
int errIndex = error.getToken().getIndex() + lastCommandOffset;
while (errIndex-- > 0) {
printErr("-");
}
for (int i = 0; i < error.getToken().getString().length(); i++) {
printErr("^");
}
printlnErr("");
printlnErr(error);
}

public void outputException(Throwable e) {
printlnErr(e);
if (e.getCause() != null) {
printlnErr(e.getCause());
}
}

private PrintStream log = null;

private boolean isLoggingEnabled() {
return log != null;
}

private int loopCounter = 0;

public void cliEnterLoop() {
if (isLoggingEnabled()) {
loopCounter++;
}
}

public void cliLeaveLoop() {
if (isLoggingEnabled()) {
loopCounter--;
}
if (loopCounter < 0) {
disableLogging();
}
}

@Command(description="Sets up logging, which duplicates all subsequent output in a file")
public void enableLogging(
@Param(name="fileName", description="Name of the logfile") String filename
) throws FileNotFoundException {

log = new PrintStream(filename);
loopCounter = 0;
}

@Command(description="Turns off logging")
public String disableLogging() {
if (log != null) {
log.close();
log = null;
return "Logging disabled";
} else return "Logging is already disabled";
}

public interface ConsoleIO {

/**
* Read command string with suggested prompt.
* Command is trimmed and have no side spaces.
*
* @param prompt prompt message should be shown before cursor
* @return trimmed string command representation
*/
String readCommand(String prompt) throws IOException;

/**
* Write command execution result to output
*
* @param commandResult command result
*/
void output(String commandResult);

/**
* Output command syntax exception
* @param input command asked to be executed
* @param error {@see TokenException} with syntax error explanation
*/
void outputException(String input, TokenException error);

/**
* Output other exception what is result of command execution
* @param e exception was thrown during command execution.
*/
void outputException(Throwable e);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.maxifier.cliche;

/**
* ConversionEngine
*
* @author aleksey.didik@maxifier.com (Aleksey Didik) (2013-07-17 16:28)
*/
public class ConversionEngine implements InputConversionEngine, OutputConversionEngine {


}
Loading