/// <summary>Reads the file text.</summary> /// <param name="inputFileDirectory">The input file directory.</param> /// <param name="inputFileName">Name of the input file.</param> /// <returns>The file text content.</returns> public string ReadFileText(string inputFileDirectory, string inputFileName) { if (string.IsNullOrEmpty(inputFileDirectory) || string.IsNullOrEmpty(inputFileName)) { return(null); } try { // Make the working directory the directory for the root ink file, // so that relative paths for INCLUDE files are correct. FileSystemInteractor.SetCurrentDirectory(inputFileDirectory); } catch (Exception exception) { ConsoleInteractor.WriteErrorMessage("Could not set directory '{0}'", exception); ConsoleInteractor.EnvironmentExitWithCodeError1(); } string fileText = null; try { fileText = FileSystemInteractor.ReadAllTextFromFile(inputFileName); } catch (Exception exception) { ConsoleInteractor.WriteErrorMessage("Could not open file '{0}'", exception); ConsoleInteractor.EnvironmentExitWithCodeError1(); } return(fileText); }
/// <summary>Set the output format.</summary> /// <param name="options"></param> public IToolOutputManagable CreateOuputManager(CommandLineToolOptions options) { // Set console's output encoding to UTF-8 ConsoleInteractor.SetEncodingToUtF8(); if (options.IsJsonOutputNeeded) { return(new JsonToolOutputManager(ConsoleInteractor)); } return(new ConsoleToolOutputManager(ConsoleInteractor)); }
/// <summary>Runs the story until continuation point.</summary> /// <param name="story">The story.</param> /// <param name="parsedFiction"></param> /// <param name="options">The options.</param> /// <returns></returns> public virtual bool RunStoryUntilContinuationPoint(Runtime.IStory story, Parsed.IFiction parsedFiction, ConsoleUserInterfaceOptions options) { if (story == null) { return(false); } var choices = story.currentChoices; bool isAutoPlayActive = options != null ? options.IsAutoPlayActive : false; if (isAutoPlayActive) { // autoPlay: Pick random choice var choiceIndex = ChoiceGenerator.GetRandomChoice(choices.Count); ConsoleInteractor.ResetConsoleColor(); } else { // Normal: Ask user for choice number OutputManager.ShowChoices(choices, options); var uiResult = GetPropperUserInteractionResult(story, parsedFiction, options); ConsoleInteractor.ResetConsoleColor(); if (uiResult == null) { return(false); } else if (uiResult.IsInputStreamClosed) { return(false); } else if (uiResult.IsValidChoice) { story.ChooseChoiceIndex(uiResult.ChosenIndex); } else if (uiResult.DivertedPath != null) { story.ChoosePathString(uiResult.DivertedPath); uiResult.DivertedPath = null; } } EvaluateStory(story, options); return(true); }
/// <summary>Does a Run with the specified options.</summary> /// <param name="options">The options.</param> public void Run(CommandLineToolOptions options) { if (options == null) { ConsoleInteractor.WriteErrorMessage("Missing options object"); ConsoleInteractor.EnvironmentExitWithCodeError1(); } // Read the file content string fileContent = ReadFileText(toolOptions.InputFileDirectory, toolOptions.InputFileName); Parsed.Fiction parsedFiction; var story = CreateStory(fileContent, options, out parsedFiction); // If we have a story without errors we have compiled successfully. var compileSuccess = !(story == null || Errors.Count > 0); OutputManager.ShowCompileSuccess(options, compileSuccess); // If we only wanted to show the stats we are done now. if (options.IsOnlyShowJsonStatsActive) { return; } PrintAllMessages(); // Without having successfully compiled we can not go on to play or flush JSON. if (!compileSuccess) { ConsoleInteractor.EnvironmentExitWithCodeError1(); } if (options.IsFountainFileOutputNeeded) { WriteStoryToFountainFile(parsedFiction, options); } if (options.IsPlayMode) { PlayStory(story, parsedFiction, options); } else { WriteStoryToJsonFile(story, options); } }
/// <summary>Writes the compiled story to a Fountain file.</summary> /// <param name="story">The story.</param> /// <param name="options">The options.</param> public void WriteStoryToFountainFile(Parsed.Fiction parsedFiction, CommandLineToolOptions options) { string fountainContent = FountainExponentialAdapter.ConvertToFountainExponential(parsedFiction, options.InputFileName); try { FileSystemInteractor.WriteAllTextToFile(options.RootedOutputFountainFilePath, fountainContent, System.Text.Encoding.UTF8); OutputManager.ShowExportComplete(options); } catch { ConsoleInteractor.WriteErrorMessage("Could not write to output file '{0}'", options.RootedOutputFilePath); ConsoleInteractor.EnvironmentExitWithCodeError1(); } }
/// <summary>Exits with the usage instructions.</summary> public void ExitWithUsageInstructions() { string usageInstructions = "Usage: inklecate2 <options> <ink file> \n" + " -o <filename>: Output file name\n" + " -c: Count all visits to knots, stitches and weave points, not\n" + " just those referenced by TURNS_SINCE and read counts.\n" + " -p: Play mode\n" + " -j: Output in JSON format (for communication with tools like Inky)\n" + " -s: Print stats about story including word count in JSON format\n" + " -v: Verbose mode - print compilation timings\n" + " -k: Keep inklecate running in play mode even after story is complete\n"; ConsoleInteractor.WriteInformation(usageInstructions); ConsoleInteractor.EnvironmentExitWithCodeError1(); }
/// <summary>Writes the compiled story to a JSON file.</summary> /// <param name="story">The story.</param> /// <param name="options">The options.</param> public void WriteStoryToJsonFile(Runtime.IStory story, CommandLineToolOptions options) { // Compile mode var jsonStr = story.ToJson(); try { FileSystemInteractor.WriteAllTextToFile(options.RootedOutputFilePath, jsonStr, System.Text.Encoding.UTF8); OutputManager.ShowExportComplete(options); } catch { ConsoleInteractor.WriteErrorMessage("Could not write to output file '{0}'", options.RootedOutputFilePath); ConsoleInteractor.EnvironmentExitWithCodeError1(); } }
/// <summary>Plays the story.</summary> /// <param name="story">The story.</param> /// <param name="compiler">The compiler.</param> /// <param name="options">The options.</param> /// <exception cref="Exception"></exception> public void PlayStory(Runtime.IStory story, Parsed.Fiction parsedFiction, CommandLineToolOptions options) { // Always allow ink external fall-backs story.allowExternalFunctionFallbacks = true; //Capture a CTRL+C key combo so we can restore the console's foreground color back to normal when exiting ConsoleInteractor.ResetColorOnCancelKeyPress(); try { ConsoleUserInterfaceOptions uiOptions = new ConsoleUserInterfaceOptions() { IsAutoPlayActive = false, IsKeepRunningAfterStoryFinishedNeeded = options.IsKeepRunningAfterStoryFinishedNeeded, IsJsonOutputNeeded = options.IsJsonOutputNeeded }; UserInterface.Begin(story, parsedFiction, uiOptions); } catch (Runtime.StoryException e) { if (e.Message.Contains("Missing function binding")) { Errors.Add(e.Message); // If you get an error while playing, just print immediately PrintAllMessages(); } else { throw e; } } catch (Exception e) { string storyPath = "<END>"; var path = story.state.currentPathString; if (path != null) { storyPath = path.ToString(); } throw new Exception(e.Message + " (Internal story path: " + storyPath + ")", e); } }
/// <summary>Parses the command line arguments.</summary> /// <param name="args">The command line arguments.</param> /// <returns>An options object.</returns> public void ParseArguments(string[] args, ParsedCommandLineOptions options) { if (args == null || args.Length == 0 || options == null) { return; } bool expectingOutputFilename = false; bool expectingPluginName = false; // Process arguments int lastArgumentIndex = args.Length - 1; for (int i = 0; i < args.Length; i++) { string argument = args[i]; if (i == lastArgumentIndex) { // When on the last argument we assume it's the file. options.InputFilePath = argument; } else if (expectingOutputFilename) { // When a output filename flag preceded the current argument we assume it's the output filename. options.OutputFilePath = argument; expectingOutputFilename = false; } else if (expectingPluginName) { // When a plug-in name flag preceded the current argument we assume it's a plug-in name. options.PluginNames.Add(argument); expectingPluginName = false; } else if (argument.StartsWith("-")) { // Determine options switch (argument) { case "-p": options.IsPlayMode = true; break; case "-v": options.IsVerboseMode = true; break; case "-j": options.IsJsonOutputNeeded = true; break; case "-s": options.IsOnlyShowJsonStatsActive = true; break; case "-o": expectingOutputFilename = true; break; case "-c": options.IsCountAllVisitsNeeded = true; break; case "-x": expectingPluginName = true; break; case "-k": options.IsKeepOpenAfterStoryFinishNeeded = true; break; default: ConsoleInteractor.WriteWarning("Unsupported argument flag: '{0}'", argument); break; } } else { ConsoleInteractor.WriteWarning("Unexpected argument: '{0}'", argument); break; } } }
public void CreateUI() { input = new StubTextReader(); output = new StringWriter(); ui = new ConsoleInteractor(input, output); }