public void CurrentDirectoryUnchangedWhenTargetDirectoryIsNull()
        {
            var state = new FileSystemState();
            var before = state.GetCurrentDirectory();
            var isSetDirectorySuccess = state.TrySetCurrentDirectory(null);
            var after = state.GetCurrentDirectory();

            Assert.IsFalse(isSetDirectorySuccess);
            Assert.AreEqual(before, after);
        }
        public void CanChangeCurrentDirectory()
        {
            var state = new FileSystemState();
            var before = state.GetCurrentDirectory();
            var target = new Directory();

            var isSetDirectorySuccess = state.TrySetCurrentDirectory(target);
            var after = state.GetCurrentDirectory();

            Assert.IsTrue(isSetDirectorySuccess);
            Assert.AreNotEqual(before, after);
            Assert.AreEqual(target, after);
        }
        public void NewStateHasCurrentDirectory()
        {
            var state = new FileSystemState();
            var current = state.GetCurrentDirectory();

            Assert.IsNotNull(current);
        }
        public void CurrentDirectoryStartsWithNoFiles()
        {
            var state = new FileSystemState();
            var current = state.GetCurrentDirectory();

            Assert.IsNotNull(current.FilesInDirectory);
            Assert.IsEmpty(current.FilesInDirectory);
        }
예제 #5
0
        public void CurrentDirectoryHasExecuteAccess()
        {
            var state         = new FileSystemState();
            var current       = state.GetCurrentDirectory();
            var currentAccess = _permissionController.GetPermissions(current);

            Assert.IsTrue(currentAccess.Execute);
        }
예제 #6
0
        public void CurrentDirectoryDoesNotHaveWriteAccess()
        {
            var state         = new FileSystemState();
            var current       = state.GetCurrentDirectory();
            var currentAccess = _permissionController.GetPermissions(current);

            Assert.IsFalse(currentAccess.Write);
        }
예제 #7
0
        public void NewStateRootDirectoryIsNotCurrentDirectory()
        {
            var state   = new FileSystemState();
            var root    = state.GetRootDirectory();
            var current = state.GetCurrentDirectory();

            Assert.AreNotEqual(root, current);
        }
예제 #8
0
        public void NewStateHomeDirectoryIsCurrentDirectory()
        {
            var state   = new FileSystemState();
            var home    = state.GetHomeDirectory();
            var current = state.GetCurrentDirectory();

            Assert.AreEqual(home, current);
        }
        public void CurrentDirectoryStartsWithRootParentDirectory()
        {
            var state = new FileSystemState();
            var current = state.GetCurrentDirectory();
            var root = state.GetRootDirectory();

            Assert.IsNotNull(current.ParentDirectory);
            Assert.AreEqual(current.ParentDirectory, root);
        }
        private string ChangeDirectoryToParent()
        {
            var currentDirectory = _fileSystemState.GetCurrentDirectory();

            if (currentDirectory.ParentDirectory == null)
            {
                return($"Error - Failed to find parent directory for `{currentDirectory.Name}`");
            }

            var isSetCurrentDirectoryAsParentDirectorySuccess = _fileSystemState.TrySetCurrentDirectory(currentDirectory.ParentDirectory);

            if (!isSetCurrentDirectoryAsParentDirectorySuccess)
            {
                return($"Error - Failed to set current directory to parent directory: `{currentDirectory.ParentDirectory.Name}");
            }

            return("Current working directory changed");
        }
예제 #11
0
        public void InitializeConsoleText(
            UserInterfaceController userInterfaceController,
            FileSystemState fileSystemState,
            DirectoryController directoryController,
            Text inputText,
            Text outputText)
        {
            Debug.Assert(inputText != null, "The input text object is not properly set.");
            Debug.Assert(outputText != null, "The output text object is not properly set.");

            // Ensure that the console text objects are empty to start (except for prompts and path metadata)
            var currentDirectory     = fileSystemState.GetCurrentDirectory();
            var currentDirectoryPath = directoryController.GetDirectoryPath(currentDirectory);

            userInterfaceController.SetUserInterfaceTextWithInputPrompt(inputText, string.Empty, currentDirectoryPath);
            userInterfaceController.SetUserInterfaceText(outputText, updatedText: string.Empty);
        }
예제 #12
0
        // Game Loop - Executed Once Per Frame
        public void Update()
        {
            // First, figure out if the user has done anything to modify the input
            var isUpArrowPressed   = Input.GetKeyDown(KeyCode.UpArrow);
            var isDownArrowPressed = Input.GetKeyDown(KeyCode.DownArrow);
            var userInputString    = Input.inputString;
            var userInteraction    = _userInterfaceController.GetUserInteraction(userInputString, isUpArrowPressed, isDownArrowPressed, _terminalState);

            // Next, if the user submitted input as part of their interactions, attempt to validate and execute what they submitted
            if (userInteraction.IsInputSubmitted)
            {
                // Need to get the current directory before we execute the command since it could change the current directory
                var currentDirectory        = _fileSystemState.GetCurrentDirectory();
                var userInteractionResponse = new StringBuilder();

                // Since the user submitted input, we now need to parse that input
                Debug.Log($"User input submitted: `{userInteraction.SubmittedInput}`");

                var isParseInputSuccess = _userInputParser.TryParseUserInput(userInteraction.SubmittedInput, out var parsedUserSubmittedInput);
                if (!isParseInputSuccess)
                {
                    Debug.Log($"Failed to parse user input: `{userInteraction.SubmittedInput}`");
                }

                // Extract the arguments into a parameterized array
                var args = parsedUserSubmittedInput.Arguments?.ToArray();

                // Check to see that the we can retrieve the command the user wants to execute from the parsed input
                var isCommandRetrievedSuccess = _commandController.TryGetCommand(_commandState, parsedUserSubmittedInput.CommandName, out var command);
                if (!isCommandRetrievedSuccess)
                {
                    userInteractionResponse.AppendLine($"Command `{parsedUserSubmittedInput.CommandName}` not found.");
                    userInteractionResponse.AppendLine($"Run `{_helpCommandName}` for a list of available commands");
                }

                // Execute the command if we successfully retrieved it
                // Note - Each command is in charge of its own validation and if / how it executes after succeeding or failing validation
                else
                {
                    var commandResponse = command.ExecuteCommand(args);
                    userInteractionResponse.AppendLine(commandResponse);
                }

                // Mark that the user's output will change based on this latest terminal command
                userInteraction.IsOutputModified = true;
                var terminalCommand = new TerminalCommand
                {
                    TerminalCommandNumber = _terminalState.GetTerminalCommandSubmissionNumber(),
                    TerminalCommandPath   = _directoryController.GetDirectoryPath(currentDirectory),
                    TerminalCommandInput  = userInteraction.SubmittedInput,
                    TerminalCommandOutput = userInteractionResponse.ToString(),

                    // If the command was a valid `clear` command, we do not want to show output for it, otherwise we do want output visible
                    IsVisibleInTerminal = command == null || command.GetType() != typeof(ClearCommand) || !command.TryValidateArguments(out _, args)
                };

                _terminalState.IncrementTerminalCommandSubmissionNumber();

                // Add the input to the list of historical inputs if it is a valid input (not empty, null, or over the character limit)
                if (_terminalState.TryValidateInput(userInteraction.SubmittedInput, out var validSubmittedInput))
                {
                    var isAddHistoricalInputSuccess = _terminalState.TryAddHistoricalCommand(terminalCommand);
                    if (!isAddHistoricalInputSuccess && _terminalState.TryRemoveOldestHistoricalCommand())
                    {
                        isAddHistoricalInputSuccess = _terminalState.TryAddHistoricalCommand(terminalCommand);
                    }

                    Debug.Assert(isAddHistoricalInputSuccess, $"Failed to add valid historical input: {validSubmittedInput} with output: {userInteractionResponse}");
                }
            }

            // Next, if the user has modified input, make sure that is reflected back in the UI
            if (userInteraction.IsInputModified)
            {
                // Grab the current directory after the command has executed, because the command could have changed the current directory
                var currentDirectory     = _fileSystemState.GetCurrentDirectory();
                var currentDirectoryPath = _directoryController.GetDirectoryPath(currentDirectory);
                _userInterfaceController.SetUserInterfaceTextWithInputPrompt(InputTextObject, userInteraction.ModifiedInput, currentDirectoryPath);
            }

            // Finally, if the user's input requires a corresponding change in output, reflect that in the UI
            if (userInteraction.IsOutputModified)
            {
                // If a command was submitted, it has already been added to the previous commands with relevant output
                // We can construct full output to the user with the list of previous commands
                var previousTerminalCommands = _terminalState.GetPreviousTerminalCommands();
                userInteraction.ModifiedOutput = _userInterfaceController.BuildUserInterfaceText(previousTerminalCommands);

                _userInterfaceController.SetUserInterfaceText(OutputTextObject, userInteraction.ModifiedOutput);
            }
        }
예제 #13
0
        public string ExecuteCommand(params string[] args)
        {
            // Validate the arguments to the command
            if (!TryValidateArguments(out var validationResponse, args))
            {
                return(validationResponse);
            }

            // Extract the arguments and flags
            string targetDirectoryName = null;
            bool   showHiddenFiles     = false;
            bool   showFileListView    = false;

            // Ignore the first parameter because we know it is the command name since validation succeeded
            for (var i = 1; i < args.Length; i++)
            {
                if (args[i].StartsWith(_flagParameterStartingCharacter.ToString(), StringComparison.InvariantCultureIgnoreCase))
                {
                    // Loop through all the flags provided like `-abcdefg` and extract each one as necessary
                    var shortOptions = args[i];
                    shortOptions = shortOptions.TrimStart(_flagParameterStartingCharacter);
                    foreach (var shortOption in shortOptions)
                    {
                        if (shortOption.Equals(_showHiddenFilesFlag))
                        {
                            showHiddenFiles = true;
                        }
                        else if (shortOption.Equals(_showFileListViewFlag))
                        {
                            showFileListView = true;
                        }
                        else
                        {
                            return($"Error - Unknown flag provided to `{GetCommandName()}`: `{shortOption}`");
                        }
                    }
                }
                else
                {
                    targetDirectoryName = args[i];
                }
            }

            // Execute the valid command logic
            Directory targetDirectory = null;

            // Handle the special case where the user wants to list the contents of the `/` or '\' directory (root)
            if (targetDirectoryName != null && targetDirectoryName.Length == 1 && _pathDelimiters.Contains(targetDirectoryName.FirstOrDefault()))
            {
                targetDirectory = _fileSystemState.GetRootDirectory();
            }

            // Handle the special case where the user wants to list the contents of the `.` directory (current directory)
            if (targetDirectoryName != null && targetDirectoryName.Equals(_currentDirectorySymbol, StringComparison.InvariantCultureIgnoreCase))
            {
                targetDirectory = _fileSystemState.GetCurrentDirectory();
            }

            // Handle the special case where the user wants to change directory to `..` (parent directory)
            if (targetDirectoryName != null && targetDirectoryName.Equals(_parentDirectorySymbol, StringComparison.InvariantCultureIgnoreCase))
            {
                var currentDirectory = _fileSystemState.GetCurrentDirectory();
                targetDirectory = currentDirectory.ParentDirectory;
                if (targetDirectory == null)
                {
                    return($"Error - Failed to find parent directory for `{currentDirectory.Name}`");
                }
            }

            // Handle the special case where the user has supplied a directory name or path they wish to see the contents of
            if (targetDirectoryName != null)
            {
                var isGetDirectorySuccess = TryGetTargetDirectory(targetDirectoryName, out targetDirectory, out var errorMessage);
                if (!isGetDirectorySuccess)
                {
                    return(errorMessage);
                }
            }

            // At this point, if we do not already have a target directory, the user did not specify a target directory to see its contents
            // If that is the case, use the "default" target directory - the current working directory
            if (targetDirectory == null)
            {
                targetDirectory = _fileSystemState.GetCurrentDirectory();
            }

            // If the user specified that they want to see the long list view, show them that view
            if (showFileListView)
            {
                return(FormatDirectoryContentsForLongView(targetDirectory, showHiddenFiles));
            }

            // Otherwise, show them the default view
            return(FormatDirectoryContents(targetDirectory, showHiddenFiles));
        }