From 8570a5293b589d0653fffc28919c93685068018d Mon Sep 17 00:00:00 2001
From: Kevin Atkinson <k@kevina.org>
Date: Sat, 15 Oct 2016 19:38:34 -0400
Subject: [PATCH] cli: refactor to expose argument parsing functionality

License: MIT
Signed-off-by: Kevin Atkinson <k@kevina.org>
---
 commands/cli/cmd_suggestion.go |  4 +++
 commands/cli/parse.go          | 49 +++++++++++++++++++---------------
 2 files changed, 31 insertions(+), 22 deletions(-)

diff --git a/commands/cli/cmd_suggestion.go b/commands/cli/cmd_suggestion.go
index 2cd699b25..8b3dae063 100644
--- a/commands/cli/cmd_suggestion.go
+++ b/commands/cli/cmd_suggestion.go
@@ -30,6 +30,10 @@ func (s suggestionSlice) Less(i, j int) bool {
 }
 
 func suggestUnknownCmd(args []string, root *cmds.Command) []string {
+	if root == nil {
+		return nil
+	}
+
 	arg := args[0]
 	var suggestions []string
 	sortableSuggestions := make(suggestionSlice, 0)
diff --git a/commands/cli/parse.go b/commands/cli/parse.go
index d69eee776..c52dd5995 100644
--- a/commands/cli/parse.go
+++ b/commands/cli/parse.go
@@ -36,27 +36,6 @@ func Parse(input []string, stdin *os.File, root *cmds.Command) (cmds.Request, *c
 		return nil, cmd, path, err
 	}
 
-	// if -r is provided, and it is associated with the package builtin
-	// recursive path option, allow recursive file paths
-	recursiveOpt := req.Option(cmds.RecShort)
-	recursive := false
-	if recursiveOpt != nil && recursiveOpt.Definition() == cmds.OptionRecursivePath {
-		recursive, _, err = recursiveOpt.Bool()
-		if err != nil {
-			return req, nil, nil, u.ErrCast()
-		}
-	}
-
-	// if '--hidden' is provided, enumerate hidden paths
-	hiddenOpt := req.Option("hidden")
-	hidden := false
-	if hiddenOpt != nil {
-		hidden, _, err = hiddenOpt.Bool()
-		if err != nil {
-			return req, nil, nil, u.ErrCast()
-		}
-	}
-
 	// This is an ugly hack to maintain our current CLI interface while fixing
 	// other stdin usage bugs. Let this serve as a warning, be careful about the
 	// choices you make, they will haunt you forever.
@@ -67,7 +46,7 @@ func Parse(input []string, stdin *os.File, root *cmds.Command) (cmds.Request, *c
 		}
 	}
 
-	stringArgs, fileArgs, err := parseArgs(stringVals, stdin, cmd.Arguments, recursive, hidden, root)
+	stringArgs, fileArgs, err := ParseArgs(req, stringVals, stdin, cmd.Arguments, root)
 	if err != nil {
 		return req, cmd, path, err
 	}
@@ -86,6 +65,32 @@ func Parse(input []string, stdin *os.File, root *cmds.Command) (cmds.Request, *c
 	return req, cmd, path, nil
 }
 
+func ParseArgs(req cmds.Request, inputs []string, stdin *os.File, argDefs []cmds.Argument, root *cmds.Command) ([]string, []files.File, error) {
+	var err error
+
+	// if -r is provided, and it is associated with the package builtin
+	// recursive path option, allow recursive file paths
+	recursiveOpt := req.Option(cmds.RecShort)
+	recursive := false
+	if recursiveOpt != nil && recursiveOpt.Definition() == cmds.OptionRecursivePath {
+		recursive, _, err = recursiveOpt.Bool()
+		if err != nil {
+			return nil, nil, u.ErrCast()
+		}
+	}
+
+	// if '--hidden' is provided, enumerate hidden paths
+	hiddenOpt := req.Option("hidden")
+	hidden := false
+	if hiddenOpt != nil {
+		hidden, _, err = hiddenOpt.Bool()
+		if err != nil {
+			return nil, nil, u.ErrCast()
+		}
+	}
+	return parseArgs(inputs, stdin, argDefs, recursive, hidden, root)
+}
+
 // Parse a command line made up of sub-commands, short arguments, long arguments and positional arguments
 func parseOpts(args []string, root *cmds.Command) (
 	path []string,
-- 
GitLab