import java.io.PrintWriter;
import java.io.Writer;
import java.lang.annotation.Annotation;
+import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
import org.kohsuke.args4j.OptionHandlerFilter;
import org.kohsuke.args4j.spi.OptionHandler;
import org.kohsuke.args4j.spi.SubCommand;
import org.tizen.ncli.ide.shell.AbstractCLI;
/**
+ * Extends {@link CmdLineParser}
* @author Harry Hyeongseok Heo{@literal <hyeongseok.heo@samsung.com>} (S-core)
*
*
*/
public class CommandLineParser extends CmdLineParser {
+ private static final String CURRENT_CMD_KEY = "CURRENT_CMD";
private Logger log = LoggerFactory.getLogger(getClass());
private AbstractCLI current;
+ private int usageWidth = 80;
public CommandLineParser(Object bean) {
super(bean);
if (null != current) {
CommandInfo cmdInfo = new CommandInfo(current.getClass());
cmdInfo.setCmdLineParser(this);
- SubCommandData.put("CURRENT_CMD", cmdInfo);
+ CommandInfo preCmd = SubCommandData.get(CURRENT_CMD_KEY);
+ log.trace("preCmd:{}",preCmd);
+ SubCommandData.put(CURRENT_CMD_KEY, cmdInfo);
findTreeNode = SubCommandData.getRootNode().findTreeNode(cmdInfo);
- if (null == findTreeNode) {
+ if (null == preCmd && null == findTreeNode) {
findTreeNode = SubCommandData.getRootNode().addChild(cmdInfo);
+ }else if( null != preCmd) {
+ TreeNode<CommandInfo> findPreTreeNode= SubCommandData.getRootNode().findTreeNode(preCmd);
+ findPreTreeNode.addChild(cmdInfo);
}
log.trace("Sub command call..Setting CURRENT_CMD...{}", cmdInfo);
} else {// In case of Main
return cmdInfo;
}
+ /*======================================= START ========================
+ * Below code is copied from org.kohsuke.args4j.CmdLineParser to modify some output format.
+ * @author Harry Hyeongseok Heo
+ * @date 2013.12.26
+ * */
+ /**
+ * Override origin method due to change output format<br>
+ * Followings are modified.
+ * <li> Exclude hidden option to calculate max length of name and meta</li>
+ * <li> remove ":" between name and usage.</li>
+ *
+ * @author Harry Hyeongseok Heo
+ * @see org.kohsuke.args4j.CmdLineParser#printUsage(java.io.Writer, java.util.ResourceBundle)
+ */
+ @Override
+ public void printUsage(Writer out, ResourceBundle rb) {
+ PrintWriter w = new PrintWriter(out);
+ List<OptionHandler> arguments2 = getArguments();
+ List<OptionHandler> options2 = getOptions();
+ // determine the length of the option + metavar first
+ // skip in case of hidden option by Harry
+ int len = 0;
+ for (OptionHandler h : arguments2) {
+ if( h.option.hidden()) continue;//Added by Harry
+ int curLen = getPrefixLen(h, rb);
+ len = Math.max(len,curLen);
+ }
+ for (OptionHandler h: options2) {
+ if( h.option.hidden()) continue;//Added by Harry
+ int curLen = getPrefixLen(h, rb);
+ len = Math.max(len,curLen);
+ }
+ log.trace("NameMeta Max:{}",len);;
+ // then print
+ for (OptionHandler h : arguments2) {
+ printOption(w, h, len, rb);
+ }
+ for (OptionHandler h : options2) {
+ printOption(w, h, len, rb);
+ }
+
+ w.flush();
+ }
+
+
+ /**
+ * Prints the usage information for a given option.
+ * @param out Writer to write into
+ * @param handler handler where to receive the informations
+ * @param len Maximum length of metadata column
+ * @param rb ResourceBundle for I18N
+ */
+ private void printOption(PrintWriter out, OptionHandler handler, int len, ResourceBundle rb) {
+ // Hiding options without usage information
+ if (handler.option.usage() == null || handler.option.usage().length() == 0 || handler.option.hidden()) {
+ return;
+ }
+
+ // What is the width of the two data columns
+ int widthMetadata = Math.min(len, (usageWidth - 4) / 2);
+ int widthUsage = usageWidth - 4 - widthMetadata;
+
+ // Line wrapping
+ List<String> namesAndMetas = wrapLines(handler.getNameAndMeta(rb), widthMetadata);
+ List<String> usages = wrapLines(localize(handler.option.usage(),rb), widthUsage);
+
+ // Output
+ for(int i=0; i<Math.max(namesAndMetas.size(), usages.size()); i++) {
+ String nameAndMeta = (i >= namesAndMetas.size()) ? "" : namesAndMetas.get(i);
+ String usage = (i >= usages.size()) ? "" : usages.get(i);
+ String format = (nameAndMeta.length() > 0)
+ ? " %1$-" + widthMetadata + "s %2$-1s"//Removed ":" by harry
+ : " %1$-" + widthMetadata + "s %2$-1s";
+ String output = String.format(format, nameAndMeta, usage);
+ out.println(output);
+ }
+ }
+
+ /**
+ * Wraps a line so that the resulting parts are not longer than a given maximum length.
+ * @param line Line to wrap
+ * @param maxLength maximum length for the resulting parts
+ * @return list of all wrapped parts
+ */
+ private List<String> wrapLines(String line, final int maxLength) {
+ List<String> rv = new ArrayList<String>();
+ for (String restOfLine : line.split("\\n")) {
+ while (restOfLine.length() > maxLength) {
+ // try to wrap at space, but don't try too hard as some languages don't even have whitespaces.
+ int lineLength;
+ String candidate = restOfLine.substring(0, maxLength);
+ int sp=candidate.lastIndexOf(' ');
+ if(sp>maxLength*3/4) lineLength=sp;
+ else lineLength=maxLength;
+ rv.add(restOfLine.substring(0, lineLength));
+ restOfLine = restOfLine.substring(lineLength).trim();
+ }
+ rv.add(restOfLine);
+ }
+ return rv;
+ }
+
+ private String localize(String s, ResourceBundle rb) {
+ if(rb!=null) return rb.getString(s);
+ return s;
+ }
+
+ private int getPrefixLen(OptionHandler h, ResourceBundle rb) {
+ if(h.option.usage().length()==0)
+ return 0;
+
+ return h.getNameAndMeta(rb).length();
+ }
+ /*======================================= END ======================== */
+
}
--- /dev/null
+/*
+ * IDE
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * Hyeongseok Heo <hyeongseok.heo@samsung.com>
+ * Kangho Kim <kh5325.kim@samsung.com>
+ *
+ * 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.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ */
+package org.tizen.ncli.ide.messages;
+
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+/**
+ * @author Harry Hyeongseok Heo{@literal <hyeongseok.heo@samsung.com>} (S-core)
+ */
+public class TizenCLINLS {
+
+ private ResourceBundle resourceBundle;
+ private Locale locale;
+
+ public TizenCLINLS() {
+ this.resourceBundle = ResourceBundle.getBundle(getClass().getName());
+ }
+
+
+ public Locale getLocale() {
+ return locale;
+ }
+ public void setLocale(Locale locale) {
+ this.locale = locale;
+ }
+ public ResourceBundle getResourceBundle() {
+ return resourceBundle;
+ }
+
+ public String get(String key) {
+ return resourceBundle.getString(key);
+ }
+
+
+
+}
--- /dev/null
+
+metaVar_keyValue=<key>=<value>
+usage_ConfigSetting=Setting Tizen CLI config with given key=value pair
\ No newline at end of file
private StopWatch stopWatch = new StopWatch();
- private File realWorkingPath;
+ private File realWorkingPath;
/**
* Set to false , if sub command do not need to print out start and finish message
/**
* @param cmdParser
+ * @throws Exception
*/
- public void execute(final CommandLineParser cmdParser) {
+ public void execute(final CommandLineParser cmdParser) throws Exception {
this.cmdParser = cmdParser;
printStarted();
stopWatch.start();
- execute();
- stopWatch.stop();
- printFinished();
+ try {
+ execute();
+ } catch (Exception e) {
+ throw e;
+ } finally {
+ stopWatch.stop();
+ printFinished();
+ }
}
private void printStarted() {
\r
import java.io.File;\r
import java.io.PrintWriter;\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.Collections;\r
import java.util.List;\r
\r
import org.apache.commons.lang3.time.StopWatch;\r
import org.kohsuke.args4j.Option;\r
+import org.kohsuke.args4j.spi.StringArrayOptionHandler;\r
import org.kohsuke.args4j.spi.StringOptionHandler;\r
import org.slf4j.Logger;\r
import org.slf4j.LoggerFactory;\r
* \r
* @author Harry Hyeongseok Heo {@literal <hyeongseok.heo@samsung.com>} (S-core)\r
*/\r
-@TizenSubCommand(name="build-web" , usage="Make a build output directory for web application.")\r
+@TizenSubCommand(name="build-web" , usage="Make a build output directory for web application")\r
public class BuildWebCLI extends AbstractCLI {\r
private Logger log = LoggerFactory.getLogger(getClass());\r
\r
@Option(name = "-opt", aliases = { "--optimize" }, usage = "Optimize option")\r
public boolean optimize;\r
\r
- @Option(name = "-out", aliases = {"--output"} ,handler=StringOptionHandler.class, usage = "Specify output directory name")\r
+ @Option(name = "-out", aliases = {"--output"} , metaVar="name",handler=StringOptionHandler.class, usage = "Specify output directory name")\r
public String outputName;\r
\r
- @Option(name = "-euf", aliases = { "--exclude-uifw" }, usage = "Specify whether exclude tizen web ui f/w or not.")\r
+ @Option(name = "-euf", aliases = { "--exclude-uifw" }, usage = "Specify whether exclude tizen web ui f/w or not")\r
public boolean excludeUIFW;\r
\r
- @Option(name = "-e", aliases = { "--exclude" }, usage = "Specify exclude file list.")\r
- public List<String> excludeList;\r
+ @Option(name = "-e", aliases = { "--exclude" }, metaVar="<file>", handler=StringArrayOptionHandler.class ,usage = "Specify exclude file list")\r
+ public String[] excludeArray;\r
+\r
+ private List<String> excludeList;\r
\r
public void execute() {\r
log.trace("Execute BuildWebCLI...");\r
if(null != outputName) {\r
command.setOutputName(outputName);\r
}\r
- if( null != excludeList) {\r
+ if( null != excludeArray) {\r
+ excludeList = new ArrayList<String>(Arrays.asList(excludeArray));\r
command.setExcludeList(excludeList);\r
}\r
command.setOptimize(optimize);\r
BuildWebParameter commandData = command.runCommand();\r
\r
progressLog.info("Output path:{}",commandData.getOutputName());\r
+ if( null != commandData.getExcludeList()) {\r
+ progressLog.info("Excluded: {}",commandData.getExcludeList());\r
+ }\r
}\r
\r
@Override\r
*/\r
package org.tizen.ncli.ide.shell;\r
\r
-import java.io.PrintWriter;\r
-import java.util.ArrayList;\r
import java.util.Collection;\r
-import java.util.Collections;\r
import java.util.HashMap;\r
-import java.util.List;\r
import java.util.Map;\r
-import java.util.SortedSet;\r
-import java.util.TreeSet;\r
\r
import org.kohsuke.args4j.Argument;\r
-import org.kohsuke.args4j.ClassParser;\r
import org.kohsuke.args4j.CmdLineException;\r
-import org.kohsuke.args4j.CmdLineParser;\r
import org.kohsuke.args4j.Option;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-import org.tizen.common.util.CollectionUtil;\r
import org.tizen.ncli.core.CommandInfo;\r
-import org.tizen.ncli.core.CommandLineParser;\r
import org.tizen.ncli.core.SubCommandData;\r
import org.tizen.ncli.core.TizenSubCommand;\r
import org.tizen.ncli.ide.Tizen;\r
-import org.tizen.ncli.ide.TizenCLIConfig;\r
import org.tizen.ncli.ide.config.Configuration;\r
-import org.tizen.ncli.ide.core.command.SetConfigCommand;\r
import org.tizen.ncli.ide.subcommands.ConfigCLICommand;\r
\r
\r
public class ConfigCLI extends AbstractCLI{\r
private Map<String, String> properties = new HashMap<String, String>();\r
\r
- @Argument(metaVar="<key>=<value>",usage="Setting given key,value pair.")\r
+ @Argument(metaVar="<key>=<value>",usage="Setting Tizen CLI config with given key=value pair")\r
private void setConfigProperty(final String property) throws CmdLineException {\r
log.trace("setConfigProperty {}",property);\r
if( null == property || property.startsWith("-")) return;\r
public class CreateCLI extends AbstractCLI {\r
private Logger log = LoggerFactory.getLogger(CreateCLI.class);\r
\r
- @Argument(index = 0, required = true, handler = TizenSubCommandHandler.class, usage = "Command is needed!")\r
+ @Argument(index = 0, required = true, handler = TizenSubCommandHandler.class, usage = "Sub-command is needed")\r
@SubCommands({ \r
@SubCommand(name = "native-project", impl = CreateNativeProjectCLI.class),\r
@SubCommand(name = "web-project", impl = CreateWebProjectCLI.class),\r
@TizenSubCommand(name="native-project" , usage="Create the tizen native project")
public class CreateNativeProjectCLI extends AbstractCLI
{
- @Option(name = "-t", aliases = { "--type" }, usage = "Specify template name")
+ @Option(name = "-t", aliases = { "--type" }, metaVar="predefined template name",usage = "Specify template name")
private String templateName;
- @Option(name = "-n", aliases = { "--name" }, usage = "Specify project name")
+ @Option(name = "-n", aliases = { "--name" },metaVar="project name", usage = "Specify project name")
private String projectName;
@Override
/**\r
* @author Harry Hyeongseok Heo{@literal <hyeongseok.heo@samsung.com>} (S-core)\r
*/\r
-@TizenSubCommand(name="security-profile" , usage="Create security profile for signing.")\r
+@TizenSubCommand(name="security-profile" , usage="Create security profile for signing")\r
public class CreateSecProfileCLI extends AbstractCLI {\r
public CreateSecProfileCLI(){\r
this.isLoggingStartFinish = false;\r
*/\r
@Override\r
public void execute() {\r
- progressLog.info("This command is under developing...\nSorry about your inconvenience.");\r
+ progressLog.info("This command is under developing...\nSorry about your inconvenience");\r
}\r
\r
}\r
@Override\r
public void execute() {\r
// TODO Auto-generated method stub\r
- progressLog.info("This command is under developing...\nSorry about your inconvenience.");\r
+ progressLog.info("This command is under developing...\nSorry about your inconvenience");\r
}\r
\r
}\r
@TizenSubCommand(name="web-project" , usage="Create the tizen web project")
public class CreateWebProjectCLI extends AbstractCLI
{
- @Option(name = "-t", aliases = { "--type" }, usage = "Specify template name")
+ @Option(name = "-t", aliases = { "--type" }, metaVar="predefined template name",usage = "Specify template name")
private String templateName;
- @Option(name = "-n", aliases = { "--name" }, usage = "Specify project name")
+ @Option(name = "-n", aliases = { "--name" }, metaVar="project name",usage = "Specify project name")
private String projectName;
/*
/**
* @author Harry Hyeongseok Heo{@literal <hyeongseok.heo@samsung.com>} (S-core)
*/
-@TizenSubCommand(name="help" , usage="Show detailed explaination for given command.")
+@TizenSubCommand(name="help" , usage="Show detailed explaination for given command")
public class HelpCLI extends AbstractCLI{
@Argument(index=0 ,required=true , metaVar="<command>")
public class InstallCLI extends AbstractCLI{
private Logger log = LoggerFactory.getLogger(getClass());
- @Option(name = "--target", usage = "Target to install the package")
+ @Option(name = "--target", usage = "Specify the target name to install the package")
private String target;
- @Option(name = "--name", aliases ="-n", usage = "The package name to install")
+ @Option(name = "--name", aliases ="-n", usage = "Specify the package file name to install")
private String name;
@Override
import java.io.PrintWriter;
import java.text.MessageFormat;
+import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.tizen.ncli.core.TizenSubCommandHandler;
import org.tizen.ncli.core.collection.TreeNode;
import org.tizen.ncli.ide.messages.TizenCLIMessages;
+import org.tizen.ncli.ide.messages.TizenCLINLS;
import org.tizen.ncli.ide.util.TargetUtil;
/**
* Use this to show progress message to User. The default level is specified with info .
*/
protected final Logger progressLog = LoggerFactory.getLogger("NCLI_PROGRESS");
+ private PrintWriter errorWriter = new PrintWriter(System.err);
@Argument(index = 0, required = true, handler = TizenSubCommandHandler.class, metaVar = "<command>", usage = "tizen <command>")
@SubCommands({ @SubCommand(name = "create", impl = CreateCLI.class),
CommandLineParser cmdParser = new CommandLineParser(this);
log.trace("Start running Tizen CLI Main class...");
log.trace("Argument count:{}", args.length);
- PrintWriter errorWriter = new PrintWriter(System.err);
+
try {
cmdParser.setUsageWidth(120);
cmdParser.parseArgument(args);
} catch (CmdLineException e) {
try {
+ TizenCLINLS nls = new TizenCLINLS();
+ Enumeration<String> keys = nls.getResourceBundle().getKeys();
+ while(keys.hasMoreElements()) {
+ String key = keys.nextElement();
+ log.trace("key:{}, value:{}",key,nls.get(key));
+ }
+
if (args.length == 0 || helpOpt) {
printDefaultCommandUsage(errorWriter);
} else if (args.length == 3 ) {
String command = args[0];
log.trace("{}", command);
+ CommandInfo currentCmdInfo = SubCommandData.get("CURRENT_CMD");
+ log.trace("currentCmdInfo: {}", currentCmdInfo);
if (null == SubCommandData.get(command)) {
- errorWriter.println(MessageFormat.format("{0}", e.getMessage()));
+ progressLog.info(MessageFormat.format("{0}", e.getMessage()));
printDefaultCommandUsage(errorWriter);
} else {
- printSubCommandOrArgUsage(command, errorWriter);
+ printSubCommandOrArgUsage(new CommandInfo(command));
+ progressLog.error(e.getMessage());
}
-
} else if (args.length > 3) {
- errorWriter.println();
- errorWriter.println(MessageFormat.format("Error: {0}", e.getMessage()));
- errorWriter.println();
+ progressLog.info("");
+ progressLog.info(MessageFormat.format("Error: {0}", e.getMessage()));
+ progressLog.info("");
CommandInfo currentCmdInfo = SubCommandData.get("CURRENT_CMD");
+ log.trace("currentCmdInfo: {}", currentCmdInfo);
if (null != currentCmdInfo) {
+ printSubCommandOrArgUsage(currentCmdInfo);
// FIXME ResourceBundle needed.
log.trace("command:{}", currentCmdInfo.getCommandName());
- currentCmdInfo.getCmdLineParser().printUsage(errorWriter, null);
+// currentCmdInfo.getCmdLineParser().printUsage(errorWriter, null);
}
}
}finally {
}
- private void printSubCommandOrArgUsage(String command, PrintWriter errorWriter) {
+ private void printSubCommandOrArgUsage(CommandInfo currentCmdInfo) {
TreeNode<CommandInfo> rootNode = SubCommandData.getRootNode();
- TreeNode<CommandInfo> findTreeNode = rootNode.findTreeNode(new CommandInfo(command));
- if (null != findTreeNode) {
- if (findTreeNode.children.size() > 0) {
- errorWriter.println(MessageFormat.format("Usage: tizen {0} <sub-command> [args]", command));
- List<TreeNode<CommandInfo>> children = findTreeNode.children;
+ TreeNode<CommandInfo> currCmdNode = rootNode.findTreeNode(currentCmdInfo);
+
+ if (null != currCmdNode) {
+ String printCommands = concatenateCommands(currCmdNode,currentCmdInfo.getCommandName());
+ progressLog.info("Usage: {}",printCommands);
+ if (currCmdNode.children.size() > 0) {
+ List<TreeNode<CommandInfo>> children = currCmdNode.children;
int maxLen = getMaxLengthForTreeNode(children)+4;
for (TreeNode<CommandInfo> treeNode : children) {
- errorWriter.printf(" %-"+maxLen+"s%s\n", treeNode.data.getCommandName(), treeNode.data.getUsage());
+ progressLog.info(String.format(" %-"+maxLen+"s%s", treeNode.data.getCommandName(), treeNode.data.getUsage()));
}
- } else {
- errorWriter.println(MessageFormat.format("Usage: tizen {0} [args]", command));
+ }else {
+ currentCmdInfo.getCmdLineParser().printUsage(errorWriter,null);
}
} else {
- log.trace("==COULD NOT REACH THIS CODE==");
+ log.error("==COULD NOT REACH THIS CODE==");
+ }
+ }
+
+ /**
+ * Make commands sequences by context .
+ * If current command is 'web-project' and it's parent command exist , it will be made like below<br>
+ * <blockquote>
+ * create web-project
+ * </blockquote>
+ * @param findTreeNode
+ * @param command
+ * @return
+ */
+ private String concatenateCommands(TreeNode<CommandInfo> findTreeNode,
+ String command) {
+ StringBuilder returnCommand = new StringBuilder("tizen ");
+ if (findTreeNode.children.size() > 0) {
+ returnCommand.append(command);
+ returnCommand.append(" ");
+ returnCommand.append("<sub-command>");
+ } else if( null != findTreeNode.parent && !"MAIN".equals(findTreeNode.parent.data.getCommandName())) {
+ returnCommand.append(makeCmdRecursively(findTreeNode));
+ returnCommand.append(command);
+ }else {
+ returnCommand.append(command);
+ }
+ returnCommand.append(" [args]");
+ return returnCommand.toString();
+ }
+
+ private String makeCmdRecursively(TreeNode<CommandInfo> current) {
+ StringBuilder returnCmd = new StringBuilder();
+ if( null != current.parent && !"MAIN".equals(current.parent.data.getCommandName())) {
+ returnCmd.append(makeCmdRecursively(current.parent));
+ }else if( !current.isRoot()){
+ returnCmd.append(current.data.getCommandName());
+ returnCmd.append(" ");
}
+ return returnCmd.toString();
}
private int getMaxLengthForTreeNode(List<TreeNode<CommandInfo>> children) {
@TizenSubCommand(name="sign" , usage="Signing for the tizen project")\r
public class SignCLI extends AbstractCLI {\r
\r
- @Option(name = "--profile" , usage="Specify profile name that is already registered.")\r
+ @Option(name = "--profile" , usage="Specify profile name that is registered in profile.xml." ,required=true)\r
private String profile;\r
\r
/* (non-Javadoc)\r
\r
} catch (IOException e) {\r
log.error(e.getMessage());\r
+ return webAppBuildData;\r
} catch (BuildException e) {\r
progressLog.error("Error occured during build!\n\t{}",e.getMessage());\r
return webAppBuildData;\r
} catch (Exception e) {\r
log.error(e.getMessage());\r
+ progressLog.error("Error occured during build!\n\t{}",e.getMessage());\r
+ return webAppBuildData;\r
}\r
progressLog.info("\nBUILD SUCCESSFUL\n");\r
return webAppBuildData;\r