diff --git a/app/MindWork AI Studio/Tools/Pandoc.cs b/app/MindWork AI Studio/Tools/Pandoc.cs
index 6f4dc906..5a99a924 100644
--- a/app/MindWork AI Studio/Tools/Pandoc.cs
+++ b/app/MindWork AI Studio/Tools/Pandoc.cs
@@ -24,31 +24,10 @@ public static partial class Pandoc
private static readonly Version FALLBACK_VERSION = new (3, 7, 0, 2);
///
- /// Prepares a ProcessStartInfo for running pandoc with the given parameters.
+ /// Prepares a Pandoc process by using the Pandoc process builder.
///
- ///
- /// Any local installation of pandoc will be preferred over the system-wide installation.
- ///
- /// The global rust service to access file system and data dir.
- /// The input file to convert.
- /// The output file to write the converted content to.
- /// The format of the input file (e.g., markdown, html, etc.).
- /// The format of the output file (e.g., pdf, docx, etc.).
- /// Additional arguments to pass to the pandoc command (optional).
- /// The ProcessStartInfo object configured to run pandoc with the specified parameters.
- public static async Task PreparePandocProcess(RustService rustService, string inputFile, string outputFile, string inputFormat, string outputFormat, string? additionalArgs = null)
- {
- var pandocExecutable = await PandocExecutablePath(rustService);
- return new (new ProcessStartInfo
- {
- FileName = pandocExecutable.Executable,
- Arguments = $"{inputFile} -f {inputFormat} -t {outputFormat} {additionalArgs ?? string.Empty} -o {outputFile}",
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- UseShellExecute = false,
- CreateNoWindow = true
- }, pandocExecutable.IsLocalInstallation);
- }
+ /// The Pandoc process builder with default settings.
+ public static PandocProcessBuilder PreparePandocProcess() => PandocProcessBuilder.Create();
///
/// Checks if pandoc is available on the system and can be started as a process or is present in AI Studio's data dir.
@@ -60,11 +39,8 @@ public static partial class Pandoc
{
try
{
- var preparedProcess = await PreparePandocProcess(rustService, string.Empty, string.Empty, string.Empty, string.Empty);
- var startInfo = preparedProcess.StartInfo;
- startInfo.Arguments = "--version";
-
- using var process = Process.Start(startInfo);
+ var preparedProcess = await PreparePandocProcess().AddArgument("--version").BuildAsync(rustService);
+ using var process = Process.Start(preparedProcess.StartInfo);
if (process == null)
{
if (showMessages)
@@ -295,51 +271,7 @@ public static partial class Pandoc
}
}
- ///
- /// Reads the os platform to determine the used executable name.
- ///
- private static string PandocExecutableName => CPU_ARCHITECTURE is RID.WIN_ARM64 or RID.WIN_X64 ? "pandoc.exe" : "pandoc";
-
- ///
- /// Returns the path to the pandoc executable.
- ///
- ///
- /// Any local installation of pandoc will be preferred over the system-wide installation.
- /// When a local installation is found, its absolute path will be returned. In case no local
- /// installation is found, the name of the pandoc executable will be returned.
- ///
- /// Global rust service to access file system and data dir.
- /// Path to the pandoc executable.
- private static async Task PandocExecutablePath(RustService rustService)
- {
- //
- // First, we try to find the pandoc executable in the data directory.
- // Any local installation should be preferred over the system-wide installation.
- //
- var localInstallationRootDirectory = await GetPandocDataFolder(rustService);
- try
- {
- var executableName = PandocExecutableName;
- var subdirectories = Directory.GetDirectories(localInstallationRootDirectory);
- foreach (var subdirectory in subdirectories)
- {
- var pandocPath = Path.Combine(subdirectory, executableName);
- if (File.Exists(pandocPath))
- return new(pandocPath, true);
- }
- }
- catch
- {
- // ignored
- }
-
- //
- // When no local installation was found, we assume that the pandoc executable is in the system PATH.
- //
- return new(PandocExecutableName, false);
- }
-
- private static async Task GetPandocDataFolder(RustService rustService) => Path.Join(await rustService.GetDataDirectory(), "pandoc");
+ public static async Task GetPandocDataFolder(RustService rustService) => Path.Join(await rustService.GetDataDirectory(), "pandoc");
[GeneratedRegex(@"pandoc(?:\.exe)?\s*([0-9]+\.[0-9]+(?:\.[0-9]+)?(?:\.[0-9]+)?)")]
private static partial Regex PandocCmdRegex();
diff --git a/app/MindWork AI Studio/Tools/PandocProcessBuilder.cs b/app/MindWork AI Studio/Tools/PandocProcessBuilder.cs
new file mode 100644
index 00000000..b34fe8b7
--- /dev/null
+++ b/app/MindWork AI Studio/Tools/PandocProcessBuilder.cs
@@ -0,0 +1,135 @@
+using System.Diagnostics;
+using System.Reflection;
+using System.Text;
+
+using AIStudio.Tools.Metadata;
+using AIStudio.Tools.Services;
+
+using SharedTools;
+
+namespace AIStudio.Tools;
+
+public sealed class PandocProcessBuilder
+{
+ private static readonly Assembly ASSEMBLY = Assembly.GetExecutingAssembly();
+ private static readonly MetaDataArchitectureAttribute META_DATA_ARCH = ASSEMBLY.GetCustomAttribute()!;
+ private static readonly RID CPU_ARCHITECTURE = META_DATA_ARCH.Architecture.ToRID();
+
+ private string? providedInputFile;
+ private string? providedOutputFile;
+ private string? providedInputFormat;
+ private string? providedOutputFormat;
+
+ private readonly List additionalArguments = new();
+
+ private PandocProcessBuilder()
+ {
+ }
+
+ public static PandocProcessBuilder Create() => new();
+
+ public PandocProcessBuilder WithInputFile(string inputFile)
+ {
+ this.providedInputFile = inputFile;
+ return this;
+ }
+
+ public PandocProcessBuilder WithOutputFile(string outputFile)
+ {
+ this.providedOutputFile = outputFile;
+ return this;
+ }
+
+ public PandocProcessBuilder WithInputFormat(string inputFormat)
+ {
+ this.providedInputFormat = inputFormat;
+ return this;
+ }
+
+ public PandocProcessBuilder WithOutputFormat(string outputFormat)
+ {
+ this.providedOutputFormat = outputFormat;
+ return this;
+ }
+
+ public PandocProcessBuilder AddArgument(string argument)
+ {
+ this.additionalArguments.Add(argument);
+ return this;
+ }
+
+ public async Task BuildAsync(RustService rustService)
+ {
+ var sbArguments = new StringBuilder();
+
+ if(!string.IsNullOrWhiteSpace(this.providedInputFile))
+ sbArguments.Append(this.providedInputFile);
+
+ if(!string.IsNullOrWhiteSpace(this.providedInputFormat))
+ sbArguments.Append($" -f {this.providedInputFormat}");
+
+ if(!string.IsNullOrWhiteSpace(this.providedOutputFormat))
+ sbArguments.Append($" -t {this.providedOutputFormat}");
+
+ foreach (var additionalArgument in this.additionalArguments)
+ sbArguments.Append($" {additionalArgument}");
+
+ if(!string.IsNullOrWhiteSpace(this.providedOutputFile))
+ sbArguments.Append($" -o {this.providedOutputFile}");
+
+ var pandocExecutable = await PandocExecutablePath(rustService);
+ return new (new ProcessStartInfo
+ {
+ FileName = pandocExecutable.Executable,
+ Arguments = sbArguments.ToString(),
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ UseShellExecute = false,
+ CreateNoWindow = true
+ }, pandocExecutable.IsLocalInstallation);
+ }
+
+ ///
+ /// Returns the path to the pandoc executable.
+ ///
+ ///
+ /// Any local installation of pandoc will be preferred over the system-wide installation.
+ /// When a local installation is found, its absolute path will be returned. In case no local
+ /// installation is found, the name of the pandoc executable will be returned.
+ ///
+ /// Global rust service to access file system and data dir.
+ /// Path to the pandoc executable.
+ private static async Task PandocExecutablePath(RustService rustService)
+ {
+ //
+ // First, we try to find the pandoc executable in the data directory.
+ // Any local installation should be preferred over the system-wide installation.
+ //
+ var localInstallationRootDirectory = await Pandoc.GetPandocDataFolder(rustService);
+ try
+ {
+ var executableName = PandocExecutableName;
+ var subdirectories = Directory.GetDirectories(localInstallationRootDirectory);
+ foreach (var subdirectory in subdirectories)
+ {
+ var pandocPath = Path.Combine(subdirectory, executableName);
+ if (File.Exists(pandocPath))
+ return new(pandocPath, true);
+ }
+ }
+ catch
+ {
+ // ignored
+ }
+
+ //
+ // When no local installation was found, we assume that the pandoc executable is in the system PATH.
+ //
+ return new(PandocExecutableName, false);
+ }
+
+ ///
+ /// Reads the os platform to determine the used executable name.
+ ///
+ private static string PandocExecutableName => CPU_ARCHITECTURE is RID.WIN_ARM64 or RID.WIN_X64 ? "pandoc.exe" : "pandoc";
+}
\ No newline at end of file