/*
* Copyright (c) 2009-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.planet57.gshell.help;
import java.io.PrintWriter;
import com.google.common.base.CharMatcher;
import com.planet57.gshell.branding.Branding;
import com.planet57.gshell.command.CommandAction;
import com.planet57.gshell.command.resolver.Node;
import com.planet57.gshell.internal.CommandHelper;
import com.planet57.gshell.shell.Shell;
import com.planet57.gshell.util.io.PrintBuffer;
import com.planet57.gshell.util.cli2.CliProcessor;
import com.planet57.gshell.util.cli2.HelpPrinter;
import com.planet57.gshell.util.pref.PreferenceDescriptor;
import com.planet57.gshell.util.pref.PreferenceProcessor;
import com.planet57.gshell.variables.Variables;
import org.codehaus.plexus.interpolation.AbstractValueSource;
import org.codehaus.plexus.interpolation.Interpolator;
import org.codehaus.plexus.interpolation.PrefixedObjectValueSource;
import org.codehaus.plexus.interpolation.PropertiesBasedValueSource;
import org.codehaus.plexus.interpolation.StringSearchInterpolator;
import org.jline.terminal.Terminal;
import com.planet57.gshell.util.i18n.I18N;
import com.planet57.gshell.util.i18n.MessageBundle;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* {@link HelpPage} for a command.
*
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
* @since 2.5
*/
public class CommandHelpPage
implements HelpPage
{
private interface Messages
extends MessageBundle
{
@DefaultMessage("ARGUMENTS")
String arguments();
@DefaultMessage("OPTIONS")
String options();
@DefaultMessage("PREFERENCES")
String preferences();
}
private static final Messages messages = I18N.create(Messages.class);
private final Node node;
private final HelpContentLoader loader;
private final CommandAction command;
public CommandHelpPage(final Node node, final HelpContentLoader loader) {
this.node = checkNotNull(node);
checkArgument(!node.isGroup());
this.loader = checkNotNull(loader);
this.command = node.getAction();
}
@Override
public String getName() {
return node.getAction().getSimpleName();
}
@Override
public String getDescription() {
return node.getAction().getDescription();
}
@Override
public int hashCode() {
return getName().hashCode();
}
// Public so that ObjectBasedValueSource can access (it really should set accessible so this is not needed)
@SuppressWarnings("unused")
public class Helper
{
private final CliProcessor clp;
private final HelpPrinter printer;
private final PreferenceProcessor pp;
public Helper(final Branding branding, final int maxWidth) {
CommandHelper help = new CommandHelper();
clp = help.createCliProcessor(command);
printer = new HelpPrinter(clp, maxWidth);
pp = new PreferenceProcessor();
pp.setBasePath(branding.getPreferencesBasePath());
pp.addBean(command);
}
public String getName() {
return command.getName();
}
public String getAbsoluteName() {
return Node.ROOT + command.getName();
}
public String getSimpleName() {
return command.getSimpleName();
}
public String getDescription() {
return command.getDescription();
}
private void printHeader(final PrintBuffer buff, final String name) {
buff.format("@|bold %s|@%n", name);
buff.println();
}
public String getArguments() {
if (clp.getArgumentDescriptors().isEmpty()) {
return "";
}
PrintBuffer buff = new PrintBuffer();
printHeader(buff, CommandHelpPage.messages.arguments());
printer.printArguments(buff, clp.getArgumentDescriptors());
return buff.toString();
}
public String getOptions() {
if (clp.getOptionDescriptors().isEmpty()) {
return "";
}
PrintBuffer buff = new PrintBuffer();
printHeader(buff, CommandHelpPage.messages.options());
printer.printOptions(buff, clp.getOptionDescriptors());
return buff.toString();
}
public String getPreferences() {
if (pp.getDescriptors().isEmpty()) {
return "";
}
PrintBuffer buff = new PrintBuffer();
printHeader(buff, CommandHelpPage.messages.preferences());
for (PreferenceDescriptor pd : pp.getDescriptors()) {
String text = String.format(" %s @|bold %s|@ (%s)",
pd.getPreferences().absolutePath(), pd.getId(), pd.getSetter().getType().getSimpleName());
buff.println(text);
}
return buff.toString();
}
public String getDetails() {
PrintBuffer buff = new PrintBuffer();
String content, last;
content = getOptions();
buff.append(content);
last = content;
content = getArguments();
if (content.length() != 0 && last.length() != 0) {
buff.println();
}
buff.append(content);
last = content;
content = getPreferences();
if (content.length() != 0 && last.length() != 0) {
buff.println();
}
buff.append(content);
// strip off any trailing white-space
return CharMatcher.whitespace().trimTrailingFrom(buff.toString());
}
}
@Override
public void render(final Shell shell, final PrintWriter out) throws Exception {
checkNotNull(shell);
checkNotNull(out);
final Branding branding = shell.getBranding();
final Terminal terminal = shell.getTerminal();
final Variables variables = shell.getVariables();
Interpolator interp = new StringSearchInterpolator("@{", "}");
interp.addValueSource(new PrefixedObjectValueSource("command.", new Helper(branding, terminal.getWidth())));
interp.addValueSource(new PrefixedObjectValueSource("branding.", branding));
interp.addValueSource(new AbstractValueSource(false)
{
@Override
public Object getValue(final String expression) {
return variables.get(expression);
}
});
interp.addValueSource(new PropertiesBasedValueSource(System.getProperties()));
String text = loader.load(command.getClass().getName(), command.getClass().getClassLoader());
out.println(interp.interpolate(text));
}
}