001 /* 002 * Copyright (C) 2012 eXo Platform SAS. 003 * 004 * This is free software; you can redistribute it and/or modify it 005 * under the terms of the GNU Lesser General Public License as 006 * published by the Free Software Foundation; either version 2.1 of 007 * the License, or (at your option) any later version. 008 * 009 * This software is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * You should have received a copy of the GNU Lesser General Public 015 * License along with this software; if not, write to the Free 016 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 017 * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 018 */ 019 package org.crsh.lang.impl.script; 020 021 import org.crsh.cli.impl.Delimiter; 022 import org.crsh.cli.impl.completion.CompletionMatch; 023 import org.crsh.cli.spi.Completion; 024 import org.crsh.lang.spi.*; 025 import org.crsh.shell.impl.command.RuntimeContextImpl; 026 import org.crsh.shell.impl.command.ShellSession; 027 import org.crsh.shell.impl.command.spi.CommandException; 028 import org.crsh.shell.impl.command.spi.CommandInvoker; 029 import org.crsh.shell.impl.command.spi.Command; 030 import org.crsh.shell.ShellResponse; 031 import org.crsh.util.Utils; 032 033 import java.util.Map; 034 import java.util.logging.Level; 035 import java.util.logging.Logger; 036 037 /** @author Julien Viet */ 038 public class ScriptRepl implements Repl { 039 040 /** . */ 041 private static final ScriptRepl instance = new ScriptRepl(); 042 043 /** . */ 044 static final Logger log = Logger.getLogger(ScriptRepl.class.getName()); 045 046 public static ScriptRepl getInstance() { 047 return instance; 048 } 049 050 /** . */ 051 private final Language lang = new Language() { 052 @Override public String getName() { return "script"; } 053 @Override public String getDisplayName() { return "Script 1.0"; } 054 @Override public boolean isActive() { return true; } 055 @Override public Repl getRepl() { return ScriptRepl.this; } 056 @Override public org.crsh.lang.spi.Compiler getCompiler() { return ScriptCompiler.instance; } 057 @Override public void init(ShellSession session) { } 058 @Override public void destroy(ShellSession session) { } 059 }; 060 061 private ScriptRepl() { 062 } 063 064 @Override 065 public Language getLanguage() { 066 return lang; 067 } 068 069 public String getName() { 070 return "script"; 071 } 072 073 @Override 074 public String getDescription() { 075 return "The Script repl provides command line interpreter with a bash like syntax"; 076 } 077 078 public ReplResponse eval(ShellSession session, String request) { 079 PipeLineFactory factory; 080 try { 081 factory = Token.parse(request).createFactory(); 082 } 083 catch (CommandException e) { 084 return new ReplResponse.Response(ShellResponse.error(e.getErrorKind(), e.getMessage(), e.getCause())); 085 } 086 if (factory != null) { 087 try { 088 CommandInvoker<Void, Object> invoker = factory.create(session); 089 return new ReplResponse.Invoke(invoker); 090 } 091 catch (CommandNotFoundException e) { 092 log.log(Level.FINER, "Could not create command", e); 093 return new ReplResponse.Response(ShellResponse.unknownCommand(e.getName())); 094 } 095 catch (CommandException e) { 096 log.log(Level.FINER, "Could not create command", e); 097 return new ReplResponse.Response(ShellResponse.error(e.getErrorKind(), e.getMessage(), e)); 098 } 099 } else { 100 return new ReplResponse.Response(ShellResponse.noCommand()); 101 } 102 } 103 104 public CompletionMatch complete(ShellSession session, String prefix) { 105 Token ast = Token.parse(prefix); 106 String termPrefix; 107 if (ast != null) { 108 Token last = ast.getLast(); 109 termPrefix = Utils.trimLeft(last.value); 110 } else { 111 termPrefix = ""; 112 } 113 114 // 115 log.log(Level.FINE, "Retained term prefix is " + termPrefix); 116 CompletionMatch completion; 117 int pos = termPrefix.indexOf(' '); 118 if (pos == -1) { 119 Completion.Builder builder = Completion.builder(termPrefix); 120 for (Map.Entry<String, String> command : session.getCommands()) { 121 String name = command.getKey(); 122 if (name.startsWith(termPrefix)) { 123 builder.add(name.substring(termPrefix.length()), true); 124 } 125 } 126 completion = new CompletionMatch(Delimiter.EMPTY, builder.build()); 127 } else { 128 String commandName = termPrefix.substring(0, pos); 129 termPrefix = termPrefix.substring(pos); 130 try { 131 Command<?> command = session.getCommand(commandName); 132 if (command != null) { 133 completion = command.complete(new RuntimeContextImpl(session, session.getContext().getAttributes()), termPrefix); 134 } else { 135 completion = new CompletionMatch(Delimiter.EMPTY, Completion.create()); 136 } 137 } 138 catch (CommandException e) { 139 log.log(Level.FINE, "Could not create command for completion of " + prefix, e); 140 completion = new CompletionMatch(Delimiter.EMPTY, Completion.create()); 141 } 142 } 143 144 // 145 return completion; 146 } 147 }