Jerminal-Javaプログラム用のターミナルエミュレーター

エントリー



こんにちは、habrauzers! Jerminalミニライブラリについてお話しすることにしました。 現在、Groovy / Javaで大規模な商業プロジェクトに取り組んでいます。 さて、私は仕事を得ました-アプリケーション用のコンソールを書くこと。 残念ながら、条件は設定されていました。サードパーティのソリューションはなく、すべてあなた自身のものです。 考え直すことなく、私は座ってそれを書きました。 詳細-カットの下。







目標



原則として、彼らは私から非常に深刻なものを必要としませんでした。 パラメーターは次のとおりです。









全体的に非常に単純なリスト。 結果を見るのが待ちきれない人のために、リポジトリへのリンクkkremen / jerminalを提供します。







コードレビュー



さて、ここまでです。 Reflectionとlambdaについて少し読んだ後、「ナイトムーブ」をすることにしました。

まず、 Executable



インターフェイスを作成しました。







Executable.java
 package org.meinkopf.console; import java.lang.reflect.InvocationTargetException; public interface Executable { Object invoke(Object[] args) throws InvocationTargetException, IllegalAccessException; }
      
      





誰も知らない場合、これを行うことができます:







 Executable ex = (args) -> { return null; } ex.invoke(someArgs);
      
      





これで、 ex.invoke(...)



呼び出すex.invoke(...)



ラムダ式が実行されます。 リフレクションをサポートするために、 Executable



を継承するBasicExecutable



クラスを作成しました。







BasicExecutable.java
 package org.meinkopf.console; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; @SuppressWarnings({ "WeakerAccess", "unused" }) public class BasicExecutable implements Executable { protected Method method; protected Object target; public BasicExecutable(Method method, Object target) { this.method = method; this.target = target; } /* Getters and Setters */ public Object invoke(Object[] args) throws InvocationTargetException, IllegalAccessException { if (args.length < method.getParameterCount()) { return "Too few arguments!\n"; //    ,     } return method.invoke(target, Arrays.copyOfRange(args, 0, method.getParameterCount())); //    ,    } }
      
      





また、コマンドリスト用のインターフェイスクラスをいくつか作成しました。それぞれCommandList



BasicCommandList



です。 基本クラスは、コマンドをMap < String, Executable >



保存しMap < String, Executable >



タイプのオブジェクトをメインクラスに返します。







非表示のテキスト
 package org.meinkopf.console; public interface CommandList { Executable get(String commandName); }
      
      





非表示のテキスト
 package org.meinkopf.console; import java.util.HashMap; import java.util.Map; @SuppressWarnings({ "unused", "WeakerAccess" }) public class BasicCommandList implements CommandList { protected Map < String, Executable > methodMap = new HashMap <>(); @Override public Executable get(String command) { return methodMap.get(command); } public void register(@SuppressWarnings("SameParameterValue") String name, Executable command) { methodMap.put(name, command); } }
      
      





Command



ユーティリティクラスは、パーサーによって解析されたコマンドを名前文字列とArrayList



引数として保存します。 ところで、引数は文字列としてのみ受け入れられます。つまり、数値も文字列として送信されます。







メインクラスはRunnable



実装しますが、これまでのところ使用していませんRunnable



メソッドを直接呼び出します。







非表示のテキスト
 package org.meinkopf.console; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Arrays; import java.util.Scanner; @SuppressWarnings({ "WeakerAccess", "unused", "SpellCheckingInspection" }) public class Jerminal implements Runnable { public static String PROMPT = " ~ $ "; public static String HEADER = "Jerminal v0.0.1 for JVM Apps\nCopyright: Karl Meinkopf, 2017\n"; protected ArrayList < Command > commandHistory = new ArrayList <>(); protected CommandList commandList = null; private Scanner scanner; public JConsole(CommandList list) { commandList = list; scanner = new Scanner(System.in); } protected Command parse(String rawCommand) { rawCommand = rawCommand.replaceAll("(\"[\\s\\S]*?\"|[\\S]+)\\s*", "$1\u0001"); rawCommand = rawCommand.replaceAll("\"([\\s\\S]*?)\"", "$1"); String[] rawList = rawCommand.split("\u0001"); ArrayList < String > args = new ArrayList <>(Arrays.asList(rawList)); String command = args.remove(0).trim(); return new Command(command, rawCommand, args); } protected Object execute(Command command) throws InvocationTargetException, IllegalAccessException { Executable executable = commandList.get(command.getName()); if (executable == null) { return "Can't find command: '" + command.getName() + "'"; } return executable.invoke(command.getArgs().toArray()); } protected void prompt( ) { System.err.println(); System.err.print(PROMPT); Command command = parse(getInputLine()); Object result; try { result = execute(command); } catch (InvocationTargetException | IllegalAccessException e) { System.err.println("Can not execute command '" + command.getName() + "'!\n\tReason: " + e.getMessage()); return; } if (result != null) System.err.println(result.toString()); } protected String getInputLine( ) { return scanner.nextLine(); } public void run( ) { System.err.println(HEADER); //noinspection InfiniteLoopStatement while (true) { prompt(); } } }
      
      





おわりに



まあ、それはライブラリ全体です。 小さいながらも、私はそれを開発し、改善する予定です。 コメントやアドバイスがある場合-私は聞いてうれしいです。








All Articles