2

Take this minimal LaTeX document:

% minimal.tex
\documentclass{article}

\begin{document}
    Hello World!
\end{document}

And this Ruby (2.5.1) script:

require 'open3'

Open3.popen3(
  'xelatex', '-interaction=nonstopmode', '"minimal.tex"'
) do |_stdin, stdout, stderr, wait_thr|
    log = stdout.readlines + stderr.readlines
    exit_status = wait_thr.value

    puts exit_status
    puts log.join('').strip!
end

Running the script, we get:

This is XeTeX, Version 3.14159265-2.6-0.99999 (TeX Live 2018) (preloaded format=xelatex)
...
! I can't find file `'"minimal.tex"''.

This is surprising. Not only because the file is there, but because both

  • Open3.popen3('xelatex -interaction=nonstopmode "minimal.tex"') do ... and
  • Open3.popen3('lualatex', '-interaction=nonstopmode', '"minimal.tex"') do ...

work just fine!

What is special about the combination of xelatex and popen3?

Raphael
  • 9,779
  • 5
  • 63
  • 94

1 Answers1

2
Open3.popen3(
  'xelatex', '-interaction=nonstopmode', 'minimal.tex'
)

works fine.

The error message tells you, the file "minimal.tex" does not exist.

With the varargs form of popen3, the commands array is passed to Process#spawn where xelatex is called with arg1=-interaction=nonstopmode and arg2=minimal.tex. The arguments are not passed to the shell. Side note, this way you can also call other processes with "complex" args, e.g. Open3.popen3('mkdir', 'directory with spaces and $SHELL').

Ad Open3.popen3('xelatex -interaction=nonstopmode "minimal.tex"'): here, the entire string is considered a command that is sent to the standard shell, and this shell takes care of the double quotes.

Ad Open3.popen3('lualatex', '-interaction=nonstopmode', '"minimal.tex"'): here I can only guess that lualatex ignores the double quotes.

See also: https://ruby-doc.org/core-2.2.0/Process.html#method-c-exec

contradictioned
  • 1,253
  • 2
  • 14
  • 26