/// <summary>Process the output file path.</summary> /// <param name="parsedOptions">The parsed options.</param> /// <param name="processedOptions">The processed options.</param> /// <param name="startingDirectory">The starting directory.</param> public void ProcesOutputFilePath(ParsedCommandLineOptions parsedOptions, CommandLineToolOptions processedOptions, string startingDirectory) { // Without a parsed object and a input file path we can't do anything. if (parsedOptions == null || processedOptions == null) { return; } // Generate an output-path when none is given. if (!string.IsNullOrEmpty(parsedOptions.OutputFilePath)) { // if the GIVEN output-path is not rooted we strip of the filename and tag the directory on it. processedOptions.RootedOutputFilePath = Path.IsPathRooted(parsedOptions.OutputFilePath) ? parsedOptions.OutputFilePath : Path.Combine(startingDirectory, parsedOptions.OutputFilePath); } else { processedOptions.GeneratedOutputFilePath = Path.ChangeExtension(parsedOptions.InputFilePath, ".ink.json"); // if the GENERATED output-path is not rooted we strip of the filename and tag the directory on it. processedOptions.RootedOutputFilePath = Path.IsPathRooted(processedOptions.GeneratedOutputFilePath) ? processedOptions.GeneratedOutputFilePath : Path.Combine(startingDirectory, processedOptions.GeneratedOutputFilePath); } }
/// <summary>Creates the story from the file contents.</summary> /// <param name="fileContent">Content of the file.</param> /// <param name="options">The options.</param> /// <param name="compiler">The compiler.</param> /// <param name="compileSuccess">if set to <c>true</c> [compile success].</param> /// <param name="finished">if set to <c>true</c> [finished].</param> /// <returns></returns> public Runtime.IStory CreateStory(string fileContent, CommandLineToolOptions options, out Parsed.Fiction parsedFiction) { Runtime.IStory story = null; if (!options.IsInputFileJson) { // Loading a normal ink file (as opposed to an already compiled JSON file) var compiler = CreateCompiler(fileContent, options); if (options.IsOnlyShowJsonStatsActive) { ShowStats(compiler, options); parsedFiction = null; } else { //Parsed.Fiction parsedFiction = null; // Full compile story = compiler.Compile(out parsedFiction); } } else { story = CreateStoryFromJson(fileContent, options); parsedFiction = null; } return(story); }
/// <summary>Creates the story from JSON.</summary> /// <param name="fileContent">Content of the file.</param> /// <param name="options">The options.</param> /// <returns></returns> private Runtime.IStory CreateStoryFromJson(string fileContent, CommandLineToolOptions options) { // Opening up a compiled JSON file for playing var story = EngineInteractor.CreateStoryFromJson(fileContent); // No purpose for loading an already compiled file other than to play it options.IsPlayMode = true; return(story); }
/// <summary>Creates the compiler with specific compiler options.</summary> /// <param name="fileContent">Content of the file.</param> /// <param name="options">The options.</param> /// <returns></returns> private IInkCompiler CreateCompiler(string fileContent, CommandLineToolOptions options) { CompilerOptions compilerOptions = new CompilerOptions { sourceFilename = options.InputFilePath, pluginNames = options.PluginNames, countAllVisits = options.IsCountAllVisitsNeeded, }; return(CompilerInteractor.CreateCompiler(fileContent, compilerOptions)); }
/// <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>Shows the stats of the compiled story.</summary> /// <param name="compiler">The compiler.</param> /// <param name="options">The options.</param> private void ShowStats(IInkCompiler compiler, CommandLineToolOptions options) { // Only want stats, don't need to code-gen var parsedStory = compiler.Parse(); // Print any errors PrintAllMessages(); // Generate stats, then print as JSON var stats = Stats.Generate(compiler.ParsedFiction); OutputManager.ShowStats(options, stats); }
/// <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>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>Process the flags by copying them from the parsed options to the processed options so we can always compare them.</summary> /// <param name="parsedOptions">The parsed options.</param> /// <param name="processedOptions">The processed options.</param> public void ProcesFlags(ParsedCommandLineOptions parsedOptions, CommandLineToolOptions processedOptions) { // Without a parsed object and a input file path we can't do anything. if (parsedOptions == null || processedOptions == null) { return; } // Most of the flags are not changed while running except for IsPlayMode. processedOptions.IsPlayMode = parsedOptions.IsPlayMode; processedOptions.IsVerboseMode = parsedOptions.IsVerboseMode; processedOptions.IsCountAllVisitsNeeded = parsedOptions.IsCountAllVisitsNeeded; processedOptions.IsOnlyShowJsonStatsActive = parsedOptions.IsOnlyShowJsonStatsActive; processedOptions.IsJsonOutputNeeded = parsedOptions.IsJsonOutputNeeded; processedOptions.IsKeepRunningAfterStoryFinishedNeeded = parsedOptions.IsKeepOpenAfterStoryFinishNeeded; processedOptions.PluginNames = parsedOptions.PluginNames; }
/// <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>Process the input file path.</summary> /// <param name="parsedOptions">The parsed options.</param> /// <param name="processedOptions">The processed options.</param> /// <param name="startingDirectory">The starting directory.</param> public void ProcesInputFilePath(ParsedCommandLineOptions parsedOptions, CommandLineToolOptions processedOptions, string startingDirectory) { // Without a parsed object and a input file path we can't do anything. if (parsedOptions == null || processedOptions == null) { return; } processedOptions.InputFilePath = parsedOptions.InputFilePath; // Get the file's actual name, needed for reading after the working directory has changed. processedOptions.InputFileName = Path.GetFileName(parsedOptions.InputFilePath); processedOptions.RootedInputFilePath = Path.IsPathRooted(parsedOptions.InputFilePath) ? parsedOptions.InputFilePath : Path.Combine(startingDirectory, parsedOptions.InputFilePath); processedOptions.InputFileDirectory = Path.GetDirectoryName(processedOptions.RootedInputFilePath); }
/// <summary>Creates the command line tool options.</summary> /// <param name="args">The arguments.</param> /// <returns></returns> private CommandLineToolOptions CreateCommandLineToolOptions(string[] args) { toolOptions = new CommandLineToolOptions(); // Getting the current dir early is better in unstable situations. string startingDirectory = Directory.GetCurrentDirectory(); var parsedOptions = new ParsedCommandLineOptions(); #if USE_NETCORE_CONFIGURATION IConfigurationRoot config = ReadConfiguration(args, parsedOptions); Logger = new LoggerConfiguration() .ReadFrom.Configuration(config) .CreateLogger(); Logger.Information("Started on {0}", _startTime); Logger.Information("Config read."); Logger.Debug("Config {@0}", config); #else Logger = new LoggerConfiguration().CreateLogger(); parsedOptions = ParseArguments(args, options); #endif if (parsedOptions == null || !parsedOptions.IsInputPathGiven) { ExitWithUsageInstructions(); } ProcesOutputFilePath(parsedOptions, toolOptions, startingDirectory); ProcesOutputFountainFilePath(parsedOptions, toolOptions, startingDirectory); ProcesInputFilePath(parsedOptions, toolOptions, startingDirectory); ProcesFlags(parsedOptions, toolOptions); return(toolOptions); }