Nesting Commands

So hello everyone, i’m making a console for my game but i’m struggling to make a command that makes multiple questions to the player, basically what i’m trying to make is:
player calls the command to create the file, console asks for the extension of the file, player inputs the extension and console creates the file with that extension.
I managed to get the creation part done, what i can’t seem to find a way to solve is making the console read the second input from the player the lines in question are 190-237 if you want to use my code as example for the solution.
Another thing to say, i didn’t make all of the code, so yeah maybe my question seems trivial compared to other part.
Any help is appreciated.
Here’s my code (since it’s really long i ignored to add the using Unity etc. etc. lines)

public delegate void CommandHandler(string[] args);

public class ConsoleController {

    #region Event declarations
    // Used to communicate with ConsoleView
    public delegate void LogChangedHandler(string[] log);
    public event LogChangedHandler logChanged;
  
    public delegate void VisibilityChangedHandler(bool visible);
    public event VisibilityChangedHandler visibilityChanged;
    #endregion

    /// <summary>
    /// Object to hold information about each command
    /// </summary>
    class CommandRegistration {
        public string command { get; private set; }
        public CommandHandler handler { get; private set; }
        public string help { get; private set; }
      
        public CommandRegistration(string command, CommandHandler handler, string help) {
            this.command = command;
            this.handler = handler;
            this.help = help;
        }
    }

    /// <summary>
    /// How many log lines should be retained?
    /// Note that strings submitted to appendLogLine with embedded newlines will be counted as a single line.
    /// </summary>
    const int scrollbackSize = 20;

    Queue<string> scrollback = new Queue<string>(scrollbackSize);
    List<string> commandHistory = new List<string>();
    Dictionary<string, CommandRegistration> commands = new Dictionary<string, CommandRegistration>();

    public string[] log { get; private set; } //Copy of scrollback as an array for easier use by ConsoleView
  
    const string repeatCmdName = "!!"; //Name of the repeat command, constant since it needs to skip these if they are in the command history
  
    public ConsoleController() {
        //When adding commands, you must add a call below to registerCommand() with its name, implementation method, and help text.
        registerCommand("babble", babble, "Example command that demonstrates how to parse arguments. babble [word] [# of times to repeat]");
        registerCommand("echo", echo, "echoes arguments back as array (for testing argument parser)");
        registerCommand("help", help, "Print this help.");
        registerCommand("snake", snake, "Launches Snake.");
        registerCommand("repeatCmdName", repeatCommand, "Repeat last command.");
        registerCommand("file", file, "Lets you create and delete files.");
        registerCommand("about", about, "About the OS.");
        registerCommand("respect", respect, "Show respect.");
        registerCommand("clr", clr, "clear console");
        registerCommand("shut_down", shut_down, "Shut down the system.");
    }
  
    void registerCommand(string command, CommandHandler handler, string help) {
        commands.Add(command, new CommandRegistration(command, handler, help));
    }
  
    public void appendLogLine(string line) {
        Debug.Log(line);
      
        if (scrollback.Count >= ConsoleController.scrollbackSize) {
            scrollback.Dequeue();
        }
        scrollback.Enqueue(line);
      
        log = scrollback.ToArray();
        if (logChanged != null) {
            logChanged(log);
        }
    }
  
    public void runCommandString(string commandString) {
        appendLogLine("$ " + commandString);
      
        string[] commandSplit = parseArguments(commandString);
        string[] args = new string[0];
        if (commandSplit.Length < 1) {
            appendLogLine(string.Format("Unable to process command '{0}'", commandString));
            return;
          
        } else if (commandSplit.Length >= 2) {
            int numArgs = commandSplit.Length - 1;
            args = new string[numArgs];
            Array.Copy(commandSplit, 1, args, 0, numArgs);
        }
        runCommand(commandSplit[0].ToLower(), args);
        commandHistory.Add(commandString);
    }
  
    public void runCommand(string command, string[] args) {
        CommandRegistration reg = null;
        if (!commands.TryGetValue(command, out reg)) {
            appendLogLine(string.Format("Unknown command '{0}', type 'help' for list.", command));
        } else {
            if (reg.handler == null) {
                appendLogLine(string.Format("Unable to process command '{0}', handler was null.", command));
            } else {
                reg.handler(args);
            }
        }
    }
  
    static string[] parseArguments(string commandString)
    {
        LinkedList<char> parmChars = new LinkedList<char>(commandString.ToCharArray());
        bool inQuote = false;
        var node = parmChars.First;
        while (node != null)
        {
            var next = node.Next;
            if (node.Value == '"') {
                inQuote = !inQuote;
                parmChars.Remove(node);
            }
            if (!inQuote && node.Value == ' ') {
                node.Value = '\n';
            }
            node = next;
        }
        char[] parmCharsArr = new char[parmChars.Count];
        parmChars.CopyTo(parmCharsArr, 0);
        return (new string(parmCharsArr)).Split(new char[] {'\n'}, StringSplitOptions.RemoveEmptyEntries);
    }

    #region Command handlers
    //Implement new commands in this region of the file.

    /// <summary>
    /// A test command to demonstrate argument checking/parsing.
    /// Will repeat the given word a specified number of times.
    /// </summary>
    void babble(string[] args) {
        if (args.Length < 2) {
            appendLogLine("Expected 2 arguments.");
            return;
        }
        string text = args[0];
        if (string.IsNullOrEmpty(text)) {
            appendLogLine("Expected arg1 to be text.");
        } else {
            int repeat = 0;
            if (!Int32.TryParse(args[1], out repeat)) {
                appendLogLine("Expected an integer for arg2.");
            } else {
                for(int i = 0; i < repeat; ++i) {
                    appendLogLine(string.Format("{0} {1}", text, i));
                }
            }
        }
    }

    void echo(string[] args) {
        StringBuilder sb = new StringBuilder();
        foreach (string arg in args)
        {
            sb.AppendFormat("{0},", arg);
        }
        sb.Remove(sb.Length - 1, 1);
        appendLogLine(sb.ToString());
    }

    void help(string[] args) {
        foreach(CommandRegistration reg in commands.Values) {
            appendLogLine(string.Format("{0}: {1}", reg.command, reg.help));
        }
    }
  
    void snake (string[] args){
        SceneManager.LoadScene("Snake");
    }
  
    void repeatCommand(string[] args) {
        for (int cmdIdx = commandHistory.Count - 1; cmdIdx >= 0; --cmdIdx) {
            string cmd = commandHistory[cmdIdx];
            if (String.Equals(repeatCmdName, cmd)) {
                continue;
            }
            runCommandString(cmd);
            break;
        }
    }

    string[] text = new string[0];
    string filecreated = "";
    string content = "";

    void file (string[] args)
    {

        string operation = args [0];
        string filename = args [1];

        if (String.Compare (operation, "create") == 0) {
            if (args.Length < 2) {
                appendLogLine ("Expected 2 arguments: first is operation to do, second is file name.");
                return;
            }
            appendLogLine (string.Format ("{0} {1}", "Created", filename));
            string path ="C:\\Users\\Public\\"+filename+".txt";
            File.Create(path);
            filename = "";
        } else if (String.Compare (operation, "delete") == 0) {
            if (args.Length < 2) {
                appendLogLine ("Expected 2 arguments: first is operation to do, second is file name.");
                return;
            }
            string path ="C:\\Users\\Public\\"+filename+".txt";
            if (File.Exists(path)) {
                filename = "";
                File.Delete(path);
                appendLogLine ("File deleted.");
            } else
                appendLogLine ("The file you are trying to delete is not there.");
        } else if (String.Compare (operation, "edit") == 0) {
            string path ="C:\\Users\\Public\\"+filename+".txt";
            if (File.Exists (path)) {
                int numArgs = args.Length - 2;
                Debug.Log (numArgs);
                text = new string[numArgs];
                int i = 2;
                while (i <= numArgs + 1) {
                    text [i - 2] = args [i];
                    Debug.Log (text [i - 2]);
                    i++;
                }
                content = String.Join (" ", text);
                File.WriteAllText (path, content);
                appendLogLine (string.Format ("{0} {1}", "You successfully edited", filecreated));
                content = "";
            } else
                appendLogLine ("The file you are trying to edit is not here.");
        } else if (String.Compare (operation, "show") == 0) {
            string path ="C:\\Users\\Public\\"+filename+".txt";
            if (File.Exists (path)) {
                content = File.ReadAllText (path);
                appendLogLine (string.Format ("{0} {1} {2} {3}", "You are observing:", filename, "with content:", content));
            }
            else
                appendLogLine ("The file you are trying to see is not there.");
        }
        else {
            appendLogLine ("Operation not found.");
        }
    }
    string respected = "";

    void respect (string[] args)
    {
        if (args.Length < 1 || args.Length > 1) {
            appendLogLine ("Expected 1 argument.");
            return;
        }
        string text = args [0];
        if (string.IsNullOrEmpty (text)) {
            appendLogLine ("Expected arg1 to be text.");
        } else if (String.Compare (text, "show") == 0) {
            if (string.IsNullOrEmpty (respected)) {
                appendLogLine ("You need to respect someone first!");
            }else{
            appendLogLine(string.Format("{0} {1}", "today you respected", respected));
            }
        }
        else {
            appendLogLine(string.Format("{0} {1}", "respect", text));
            respected = text;
        }
    }

    void clr(string[] args)
    {
        for(int i=0;i<=scrollbackSize;i++){
            appendLogLine("");
        }
    }
    void shut_down (string[] args)
    {
        SceneManager.LoadScene("Apartment");
    }

    #endregion
}

Why not just include the file extension with the name of the file?

Whatever method is calling the runCommandString is getting the text input somehow. However you’re doing that, you’ll need to do the same in the delegate for the command.

Otherwise you’ll need to give the command handler internal state as well as the ability to listen to the log changed events.

yeah it can be done that way, thanks for the hint :wink:

Yeah runCommandString is taking the text from an inputfield in another script, if i get it right you are telling me that i should put another inputfield, in consolecontroller, i tried that (probably did the wrong way) since it then doesn’t let me attach the script as a component to any of the game objects in order to set the inputfield and i can’t figure out a way to “use” the inputfield from the other script.
Thanks for your time btw.