summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2011-09-21 23:53:04 +0000
committerKarl Berry <karl@freefriends.org>2011-09-21 23:53:04 +0000
commitc6249bba9d13512fb5a993a99ae95fd39f0ceced (patch)
tree94294700255544a309e883344ac3b3be6ec730be
parentb86f8cc2e0150a123620c45d3021145fc5f39381 (diff)
new script texliveonfly (19sep11)
git-svn-id: svn://tug.org/texlive/trunk@24062 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r--Build/source/texk/texlive/linked_scripts/Makefile.am1
-rw-r--r--Build/source/texk/texlive/linked_scripts/Makefile.in1
-rwxr-xr-xBuild/source/texk/texlive/linked_scripts/texliveonfly/texliveonfly.py183
l---------Master/bin/alpha-linux/texliveonfly1
l---------Master/bin/amd64-freebsd/texliveonfly1
l---------Master/bin/amd64-kfreebsd/texliveonfly1
l---------Master/bin/i386-cygwin/texliveonfly1
l---------Master/bin/i386-freebsd/texliveonfly1
l---------Master/bin/i386-kfreebsd/texliveonfly1
l---------Master/bin/i386-linux/texliveonfly1
l---------Master/bin/i386-netbsd/texliveonfly1
l---------Master/bin/i386-solaris/texliveonfly1
l---------Master/bin/mips-irix/texliveonfly1
l---------Master/bin/powerpc-aix/texliveonfly1
l---------Master/bin/powerpc-linux/texliveonfly1
l---------Master/bin/sparc-linux/texliveonfly1
l---------Master/bin/sparc-solaris/texliveonfly1
l---------Master/bin/universal-darwin/texliveonfly1
-rwxr-xr-xMaster/bin/win32/texliveonfly.exebin0 -> 1536 bytes
l---------Master/bin/x86_64-darwin/texliveonfly1
l---------Master/bin/x86_64-linux/texliveonfly1
l---------Master/bin/x86_64-solaris/texliveonfly1
-rw-r--r--Master/texmf-dist/doc/support/texliveonfly/README13
-rwxr-xr-xMaster/texmf-dist/scripts/texliveonfly/texliveonfly.py183
-rwxr-xr-xMaster/tlpkg/bin/tlpkg-ctan-check2
-rwxr-xr-xMaster/tlpkg/libexec/ctan2tds1
-rw-r--r--Master/tlpkg/tlpsrc/collection-binextra.tlpsrc1
-rw-r--r--Master/tlpkg/tlpsrc/texliveonfly.tlpsrc1
28 files changed, 403 insertions, 1 deletions
diff --git a/Build/source/texk/texlive/linked_scripts/Makefile.am b/Build/source/texk/texlive/linked_scripts/Makefile.am
index 2f2f1b2a561..63dfb373051 100644
--- a/Build/source/texk/texlive/linked_scripts/Makefile.am
+++ b/Build/source/texk/texlive/linked_scripts/Makefile.am
@@ -119,6 +119,7 @@ texmf_dist_other_scripts = \
texdef/texdef.pl \
texdiff/texdiff \
texdirflatten/texdirflatten \
+ texliveonfly/texliveonfly.py \
texloganalyser/texloganalyser \
thumbpdf/thumbpdf.pl \
ulqda/ulqda.pl \
diff --git a/Build/source/texk/texlive/linked_scripts/Makefile.in b/Build/source/texk/texlive/linked_scripts/Makefile.in
index 48df75f5ad3..be1ae9f0b6d 100644
--- a/Build/source/texk/texlive/linked_scripts/Makefile.in
+++ b/Build/source/texk/texlive/linked_scripts/Makefile.in
@@ -257,6 +257,7 @@ texmf_dist_other_scripts = \
texdef/texdef.pl \
texdiff/texdiff \
texdirflatten/texdirflatten \
+ texliveonfly/texliveonfly.py \
texloganalyser/texloganalyser \
thumbpdf/thumbpdf.pl \
ulqda/ulqda.pl \
diff --git a/Build/source/texk/texlive/linked_scripts/texliveonfly/texliveonfly.py b/Build/source/texk/texlive/linked_scripts/texliveonfly/texliveonfly.py
new file mode 100755
index 00000000000..7e5a61d3918
--- /dev/null
+++ b/Build/source/texk/texlive/linked_scripts/texliveonfly/texliveonfly.py
@@ -0,0 +1,183 @@
+#!/usr/bin/env python3
+
+# texliveonfly.py (formerly lualatexonfly.py) - "Downloading on the fly"
+# (similar to miktex) for texlive.
+#
+# Given a .tex file, runs lualatex (by default) repeatedly, using error messages
+# to install missing packages.
+#
+#
+# September 19, 2011 Release
+#
+# Written on Ubuntu 10.04 with TexLive 2011
+# Other systems may have not been tested.
+#
+# Copyright (C) 2011 Saitulaa Naranong
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/copyleft/gpl.html>.
+
+import re, subprocess, os, time, optparse, sys
+
+#sets up temp directory and paths
+tempDirectory = os.path.join(os.getenv("HOME"), ".texliveonfly")
+lockfilePath = os.path.join(tempDirectory, "newterminal_lock")
+
+#makes sure the temp directory exists
+try:
+ os.mkdir(tempDirectory)
+except OSError:
+ print("Our temp directory " + tempDirectory + " already exists; good.")
+
+checkedForUpdates = False #have we checked for updates yet?
+
+#NOTE: double-escaping \\ is neccessary for a slash to appear in the bash command
+def spawnInNewTerminal(bashCommand):
+ #creates lock file
+ lockfile = open(lockfilePath, 'w')
+ lockfile.write("texliveonfly currently performing task in separate terminal.")
+ lockfile.close()
+
+ #adds line to remove lock at end of command
+ bashCommand += '; rm \\"' + lockfilePath + '\\"'
+
+ #runs the bash command in a new terminal
+ process = subprocess.Popen (
+ ['x-terminal-emulator', '-e', 'sh -c "{0}"'.format(bashCommand) ]
+ , stdout=subprocess.PIPE )
+ process.wait()
+
+ #doesn't let us proceed until the lock file has been removed by the bash command
+ while os.path.exists(lockfilePath):
+ time.sleep(0.1)
+
+def updateTLMGR():
+ global checkedForUpdates
+ if not checkedForUpdates:
+ spawnInNewTerminal('''echo \\"Updating tlmgr prior to installing packages\n(this is necessary to avoid complaints from itself).\\n\\" ; sudo tlmgr update --self''')
+ checkedForUpdates = True
+
+#strictmatch requires an entire /file match in the search results
+def getSearchResults(preamble, term, strictMatch):
+ output = subprocess.getoutput("tlmgr search --global --file " + term)
+ outList = output.split("\n")
+
+ results = ["latex"] #latex entry for removal later
+
+ for line in outList:
+ line = line.strip()
+ if line.startswith(preamble) and (not strictMatch or line.endswith("/" + term)):
+ #filters out the package in:
+ # texmf-dist/.../package/file
+ #and adds it to packages
+ results.append(line.split("/")[-2].strip())
+ results.append(line.split("/")[-3].strip()) #occasionally the package is one more slash before
+
+ results = list(set(results)) #removes duplicates
+ results.remove("latex") #removes most common fake result
+ return results
+
+def getFilePackage(file):
+ return " ".join( getSearchResults("texmf-dist/", file, True) )
+
+def getFontPackage(font):
+ font = re.sub(r"\((.*)\)", "", font) #gets rid of parentheses
+ results = getSearchResults("texmf-dist/fonts/", font , False)
+
+ #allow for possibility of lowercase
+ if len(results) == 0:
+ return "" if font.islower() else getFontPackage(font.lower())
+ else:
+ return " ".join(results)
+
+#string can contain more than one package
+def installPackages(packagesString):
+ updateTLMGR() #avoids complaints about tlmgr not being updated
+
+ #New terminal is required: we're not guaranteed user can input sudo password into editor
+ print("Attempting to install LaTex package(s): " + packagesString )
+ print("A new terminal will open and you may be prompted for your sudo password.")
+
+ #bash command to download and remove lock
+ bashCommand='''echo \\"Attempting to install LaTeX package(s): {0} \\"
+echo \\"(Some of them might not be real.)\\n\\"
+sudo tlmgr install {0}'''.format(packagesString)
+
+ spawnInNewTerminal(bashCommand)
+
+### MAIN PROGRAM ###
+licenseinfo = """texliveonfly.py Copyright (C) 2011 Saitulaa Naranong
+This program comes with ABSOLUTELY NO WARRANTY;
+See the GNU General Public License v3 for more info."""
+
+defaultArgs = "-synctex=1 -interaction=nonstopmode"
+
+if __name__ == '__main__':
+ # Parse command line
+ parser = optparse.OptionParser(
+ usage="\n\n\t%prog [options] file.tex\n\nUse option --help for more info.\n\n" + licenseinfo ,
+ version='2011.20.9',
+ conflict_handler='resolve'
+ )
+
+ parser.add_option('-h', '--help',
+ action='help', help='print this help text and exit')
+ parser.add_option('-e', '--engine',
+ dest='engine', metavar='ENGINE', help='your LaTeX compiler; defaults to lualatex', default="lualatex")
+ parser.add_option('-a', '--arguments',
+ dest='arguments', metavar='ARGS', help='arguments to send to engine; default is: "{0}"'.format(defaultArgs) , default=defaultArgs)
+ parser.add_option('-f', '--fail_silently', action = "store_true" ,
+ dest='fail_silently', help="If tlmgr cannot be found, compile document anyway.", default=False)
+
+ (options, args) = parser.parse_args()
+
+ if len(args) == 0:
+ parser.error("You must specify a .tex file to compile.")
+
+ latexDocName = args[0]
+
+ if "not found" in subprocess.getoutput("tlmgr"):
+ if options.fail_silently:
+ subprocess.getoutput( options.engine + ' ' + options.arguments + ' "' + latexDocName + '"')
+ sys.exit(0)
+ else:
+ parser.error("It appears tlmgr is not installed. Are you sure you have TeX Live 2010 or later?")
+
+ #loop constraints
+ done = False
+ previousFile = ""
+ previousFontFile = ""
+ previousFont =""
+
+ #keeps running until all missing font/file errors are gone, or the same ones persist in all categories
+ while not done:
+ output = subprocess.getoutput( options.engine + ' ' + options.arguments + ' "' + latexDocName + '"')
+
+ #most reliable: searches for missing file
+ filesSearch = re.findall(r"! LaTeX Error: File `([^`']*)' not found" , output) + re.findall(r"! I can't find file `([^`']*)'." , output)
+ #next most reliable: infers filename from font error
+ fontsFileSearch = [ name + ".tfm" for name in re.findall(r"! Font \\[^=]*=([^\s]*)\s", output) ]
+ #brute force search for font name in files
+ fontsSearch = re.findall(r"! Font [^\n]*file\:([^\:\n]*)\:", output) + re.findall(r"! Font \\[^/]*/([^/]*)/", output)
+
+ if len(filesSearch) > 0 and filesSearch[0] != previousFile:
+ installPackages(getFilePackage(filesSearch[0]))
+ previousFile = filesSearch[0]
+ elif len(fontsFileSearch) > 0 and fontsFileSearch[0] != previousFontFile:
+ installPackages(getFilePackage(fontsFileSearch[0]))
+ previousFontFile = fontsFileSearch[0]
+ elif len(fontsSearch) > 0 and fontsSearch[0] != previousFont:
+ installPackages(getFontPackage(fontsSearch[0]))
+ previousFont = fontsSearch[0]
+ else:
+ done = True
diff --git a/Master/bin/alpha-linux/texliveonfly b/Master/bin/alpha-linux/texliveonfly
new file mode 120000
index 00000000000..f8d287e2c96
--- /dev/null
+++ b/Master/bin/alpha-linux/texliveonfly
@@ -0,0 +1 @@
+../../texmf-dist/scripts/texliveonfly/texliveonfly.py \ No newline at end of file
diff --git a/Master/bin/amd64-freebsd/texliveonfly b/Master/bin/amd64-freebsd/texliveonfly
new file mode 120000
index 00000000000..f8d287e2c96
--- /dev/null
+++ b/Master/bin/amd64-freebsd/texliveonfly
@@ -0,0 +1 @@
+../../texmf-dist/scripts/texliveonfly/texliveonfly.py \ No newline at end of file
diff --git a/Master/bin/amd64-kfreebsd/texliveonfly b/Master/bin/amd64-kfreebsd/texliveonfly
new file mode 120000
index 00000000000..f8d287e2c96
--- /dev/null
+++ b/Master/bin/amd64-kfreebsd/texliveonfly
@@ -0,0 +1 @@
+../../texmf-dist/scripts/texliveonfly/texliveonfly.py \ No newline at end of file
diff --git a/Master/bin/i386-cygwin/texliveonfly b/Master/bin/i386-cygwin/texliveonfly
new file mode 120000
index 00000000000..f8d287e2c96
--- /dev/null
+++ b/Master/bin/i386-cygwin/texliveonfly
@@ -0,0 +1 @@
+../../texmf-dist/scripts/texliveonfly/texliveonfly.py \ No newline at end of file
diff --git a/Master/bin/i386-freebsd/texliveonfly b/Master/bin/i386-freebsd/texliveonfly
new file mode 120000
index 00000000000..f8d287e2c96
--- /dev/null
+++ b/Master/bin/i386-freebsd/texliveonfly
@@ -0,0 +1 @@
+../../texmf-dist/scripts/texliveonfly/texliveonfly.py \ No newline at end of file
diff --git a/Master/bin/i386-kfreebsd/texliveonfly b/Master/bin/i386-kfreebsd/texliveonfly
new file mode 120000
index 00000000000..f8d287e2c96
--- /dev/null
+++ b/Master/bin/i386-kfreebsd/texliveonfly
@@ -0,0 +1 @@
+../../texmf-dist/scripts/texliveonfly/texliveonfly.py \ No newline at end of file
diff --git a/Master/bin/i386-linux/texliveonfly b/Master/bin/i386-linux/texliveonfly
new file mode 120000
index 00000000000..f8d287e2c96
--- /dev/null
+++ b/Master/bin/i386-linux/texliveonfly
@@ -0,0 +1 @@
+../../texmf-dist/scripts/texliveonfly/texliveonfly.py \ No newline at end of file
diff --git a/Master/bin/i386-netbsd/texliveonfly b/Master/bin/i386-netbsd/texliveonfly
new file mode 120000
index 00000000000..f8d287e2c96
--- /dev/null
+++ b/Master/bin/i386-netbsd/texliveonfly
@@ -0,0 +1 @@
+../../texmf-dist/scripts/texliveonfly/texliveonfly.py \ No newline at end of file
diff --git a/Master/bin/i386-solaris/texliveonfly b/Master/bin/i386-solaris/texliveonfly
new file mode 120000
index 00000000000..f8d287e2c96
--- /dev/null
+++ b/Master/bin/i386-solaris/texliveonfly
@@ -0,0 +1 @@
+../../texmf-dist/scripts/texliveonfly/texliveonfly.py \ No newline at end of file
diff --git a/Master/bin/mips-irix/texliveonfly b/Master/bin/mips-irix/texliveonfly
new file mode 120000
index 00000000000..f8d287e2c96
--- /dev/null
+++ b/Master/bin/mips-irix/texliveonfly
@@ -0,0 +1 @@
+../../texmf-dist/scripts/texliveonfly/texliveonfly.py \ No newline at end of file
diff --git a/Master/bin/powerpc-aix/texliveonfly b/Master/bin/powerpc-aix/texliveonfly
new file mode 120000
index 00000000000..f8d287e2c96
--- /dev/null
+++ b/Master/bin/powerpc-aix/texliveonfly
@@ -0,0 +1 @@
+../../texmf-dist/scripts/texliveonfly/texliveonfly.py \ No newline at end of file
diff --git a/Master/bin/powerpc-linux/texliveonfly b/Master/bin/powerpc-linux/texliveonfly
new file mode 120000
index 00000000000..f8d287e2c96
--- /dev/null
+++ b/Master/bin/powerpc-linux/texliveonfly
@@ -0,0 +1 @@
+../../texmf-dist/scripts/texliveonfly/texliveonfly.py \ No newline at end of file
diff --git a/Master/bin/sparc-linux/texliveonfly b/Master/bin/sparc-linux/texliveonfly
new file mode 120000
index 00000000000..f8d287e2c96
--- /dev/null
+++ b/Master/bin/sparc-linux/texliveonfly
@@ -0,0 +1 @@
+../../texmf-dist/scripts/texliveonfly/texliveonfly.py \ No newline at end of file
diff --git a/Master/bin/sparc-solaris/texliveonfly b/Master/bin/sparc-solaris/texliveonfly
new file mode 120000
index 00000000000..f8d287e2c96
--- /dev/null
+++ b/Master/bin/sparc-solaris/texliveonfly
@@ -0,0 +1 @@
+../../texmf-dist/scripts/texliveonfly/texliveonfly.py \ No newline at end of file
diff --git a/Master/bin/universal-darwin/texliveonfly b/Master/bin/universal-darwin/texliveonfly
new file mode 120000
index 00000000000..f8d287e2c96
--- /dev/null
+++ b/Master/bin/universal-darwin/texliveonfly
@@ -0,0 +1 @@
+../../texmf-dist/scripts/texliveonfly/texliveonfly.py \ No newline at end of file
diff --git a/Master/bin/win32/texliveonfly.exe b/Master/bin/win32/texliveonfly.exe
new file mode 100755
index 00000000000..5777d90a17a
--- /dev/null
+++ b/Master/bin/win32/texliveonfly.exe
Binary files differ
diff --git a/Master/bin/x86_64-darwin/texliveonfly b/Master/bin/x86_64-darwin/texliveonfly
new file mode 120000
index 00000000000..f8d287e2c96
--- /dev/null
+++ b/Master/bin/x86_64-darwin/texliveonfly
@@ -0,0 +1 @@
+../../texmf-dist/scripts/texliveonfly/texliveonfly.py \ No newline at end of file
diff --git a/Master/bin/x86_64-linux/texliveonfly b/Master/bin/x86_64-linux/texliveonfly
new file mode 120000
index 00000000000..f8d287e2c96
--- /dev/null
+++ b/Master/bin/x86_64-linux/texliveonfly
@@ -0,0 +1 @@
+../../texmf-dist/scripts/texliveonfly/texliveonfly.py \ No newline at end of file
diff --git a/Master/bin/x86_64-solaris/texliveonfly b/Master/bin/x86_64-solaris/texliveonfly
new file mode 120000
index 00000000000..f8d287e2c96
--- /dev/null
+++ b/Master/bin/x86_64-solaris/texliveonfly
@@ -0,0 +1 @@
+../../texmf-dist/scripts/texliveonfly/texliveonfly.py \ No newline at end of file
diff --git a/Master/texmf-dist/doc/support/texliveonfly/README b/Master/texmf-dist/doc/support/texliveonfly/README
new file mode 100644
index 00000000000..24387360683
--- /dev/null
+++ b/Master/texmf-dist/doc/support/texliveonfly/README
@@ -0,0 +1,13 @@
+This script performs "on the fly" downloads of missing packages on compilation,
+a feature that many missed from MiKTeX. To use it, replace your
+lualatex/pdflatex/etc command with a call to this script, e.g.
+
+texliveonfly.py file.tex
+
+[Current default options are --engine=lualatex and
+--arguments="-synctex=1 -interaction=nonstopmode"; these can be changed.]
+
+The script was written on Ubuntu and should (hopefully) be compatible with
+linux distributions. Because it is strongly dependent on tlmgr, it can
+only be used with TeX Live 2010 or later.
+
diff --git a/Master/texmf-dist/scripts/texliveonfly/texliveonfly.py b/Master/texmf-dist/scripts/texliveonfly/texliveonfly.py
new file mode 100755
index 00000000000..7e5a61d3918
--- /dev/null
+++ b/Master/texmf-dist/scripts/texliveonfly/texliveonfly.py
@@ -0,0 +1,183 @@
+#!/usr/bin/env python3
+
+# texliveonfly.py (formerly lualatexonfly.py) - "Downloading on the fly"
+# (similar to miktex) for texlive.
+#
+# Given a .tex file, runs lualatex (by default) repeatedly, using error messages
+# to install missing packages.
+#
+#
+# September 19, 2011 Release
+#
+# Written on Ubuntu 10.04 with TexLive 2011
+# Other systems may have not been tested.
+#
+# Copyright (C) 2011 Saitulaa Naranong
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/copyleft/gpl.html>.
+
+import re, subprocess, os, time, optparse, sys
+
+#sets up temp directory and paths
+tempDirectory = os.path.join(os.getenv("HOME"), ".texliveonfly")
+lockfilePath = os.path.join(tempDirectory, "newterminal_lock")
+
+#makes sure the temp directory exists
+try:
+ os.mkdir(tempDirectory)
+except OSError:
+ print("Our temp directory " + tempDirectory + " already exists; good.")
+
+checkedForUpdates = False #have we checked for updates yet?
+
+#NOTE: double-escaping \\ is neccessary for a slash to appear in the bash command
+def spawnInNewTerminal(bashCommand):
+ #creates lock file
+ lockfile = open(lockfilePath, 'w')
+ lockfile.write("texliveonfly currently performing task in separate terminal.")
+ lockfile.close()
+
+ #adds line to remove lock at end of command
+ bashCommand += '; rm \\"' + lockfilePath + '\\"'
+
+ #runs the bash command in a new terminal
+ process = subprocess.Popen (
+ ['x-terminal-emulator', '-e', 'sh -c "{0}"'.format(bashCommand) ]
+ , stdout=subprocess.PIPE )
+ process.wait()
+
+ #doesn't let us proceed until the lock file has been removed by the bash command
+ while os.path.exists(lockfilePath):
+ time.sleep(0.1)
+
+def updateTLMGR():
+ global checkedForUpdates
+ if not checkedForUpdates:
+ spawnInNewTerminal('''echo \\"Updating tlmgr prior to installing packages\n(this is necessary to avoid complaints from itself).\\n\\" ; sudo tlmgr update --self''')
+ checkedForUpdates = True
+
+#strictmatch requires an entire /file match in the search results
+def getSearchResults(preamble, term, strictMatch):
+ output = subprocess.getoutput("tlmgr search --global --file " + term)
+ outList = output.split("\n")
+
+ results = ["latex"] #latex entry for removal later
+
+ for line in outList:
+ line = line.strip()
+ if line.startswith(preamble) and (not strictMatch or line.endswith("/" + term)):
+ #filters out the package in:
+ # texmf-dist/.../package/file
+ #and adds it to packages
+ results.append(line.split("/")[-2].strip())
+ results.append(line.split("/")[-3].strip()) #occasionally the package is one more slash before
+
+ results = list(set(results)) #removes duplicates
+ results.remove("latex") #removes most common fake result
+ return results
+
+def getFilePackage(file):
+ return " ".join( getSearchResults("texmf-dist/", file, True) )
+
+def getFontPackage(font):
+ font = re.sub(r"\((.*)\)", "", font) #gets rid of parentheses
+ results = getSearchResults("texmf-dist/fonts/", font , False)
+
+ #allow for possibility of lowercase
+ if len(results) == 0:
+ return "" if font.islower() else getFontPackage(font.lower())
+ else:
+ return " ".join(results)
+
+#string can contain more than one package
+def installPackages(packagesString):
+ updateTLMGR() #avoids complaints about tlmgr not being updated
+
+ #New terminal is required: we're not guaranteed user can input sudo password into editor
+ print("Attempting to install LaTex package(s): " + packagesString )
+ print("A new terminal will open and you may be prompted for your sudo password.")
+
+ #bash command to download and remove lock
+ bashCommand='''echo \\"Attempting to install LaTeX package(s): {0} \\"
+echo \\"(Some of them might not be real.)\\n\\"
+sudo tlmgr install {0}'''.format(packagesString)
+
+ spawnInNewTerminal(bashCommand)
+
+### MAIN PROGRAM ###
+licenseinfo = """texliveonfly.py Copyright (C) 2011 Saitulaa Naranong
+This program comes with ABSOLUTELY NO WARRANTY;
+See the GNU General Public License v3 for more info."""
+
+defaultArgs = "-synctex=1 -interaction=nonstopmode"
+
+if __name__ == '__main__':
+ # Parse command line
+ parser = optparse.OptionParser(
+ usage="\n\n\t%prog [options] file.tex\n\nUse option --help for more info.\n\n" + licenseinfo ,
+ version='2011.20.9',
+ conflict_handler='resolve'
+ )
+
+ parser.add_option('-h', '--help',
+ action='help', help='print this help text and exit')
+ parser.add_option('-e', '--engine',
+ dest='engine', metavar='ENGINE', help='your LaTeX compiler; defaults to lualatex', default="lualatex")
+ parser.add_option('-a', '--arguments',
+ dest='arguments', metavar='ARGS', help='arguments to send to engine; default is: "{0}"'.format(defaultArgs) , default=defaultArgs)
+ parser.add_option('-f', '--fail_silently', action = "store_true" ,
+ dest='fail_silently', help="If tlmgr cannot be found, compile document anyway.", default=False)
+
+ (options, args) = parser.parse_args()
+
+ if len(args) == 0:
+ parser.error("You must specify a .tex file to compile.")
+
+ latexDocName = args[0]
+
+ if "not found" in subprocess.getoutput("tlmgr"):
+ if options.fail_silently:
+ subprocess.getoutput( options.engine + ' ' + options.arguments + ' "' + latexDocName + '"')
+ sys.exit(0)
+ else:
+ parser.error("It appears tlmgr is not installed. Are you sure you have TeX Live 2010 or later?")
+
+ #loop constraints
+ done = False
+ previousFile = ""
+ previousFontFile = ""
+ previousFont =""
+
+ #keeps running until all missing font/file errors are gone, or the same ones persist in all categories
+ while not done:
+ output = subprocess.getoutput( options.engine + ' ' + options.arguments + ' "' + latexDocName + '"')
+
+ #most reliable: searches for missing file
+ filesSearch = re.findall(r"! LaTeX Error: File `([^`']*)' not found" , output) + re.findall(r"! I can't find file `([^`']*)'." , output)
+ #next most reliable: infers filename from font error
+ fontsFileSearch = [ name + ".tfm" for name in re.findall(r"! Font \\[^=]*=([^\s]*)\s", output) ]
+ #brute force search for font name in files
+ fontsSearch = re.findall(r"! Font [^\n]*file\:([^\:\n]*)\:", output) + re.findall(r"! Font \\[^/]*/([^/]*)/", output)
+
+ if len(filesSearch) > 0 and filesSearch[0] != previousFile:
+ installPackages(getFilePackage(filesSearch[0]))
+ previousFile = filesSearch[0]
+ elif len(fontsFileSearch) > 0 and fontsFileSearch[0] != previousFontFile:
+ installPackages(getFilePackage(fontsFileSearch[0]))
+ previousFontFile = fontsFileSearch[0]
+ elif len(fontsSearch) > 0 and fontsSearch[0] != previousFont:
+ installPackages(getFontPackage(fontsSearch[0]))
+ previousFont = fontsSearch[0]
+ else:
+ done = True
diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check
index e0fe228b85f..a1c82223742 100755
--- a/Master/tlpkg/bin/tlpkg-ctan-check
+++ b/Master/tlpkg/bin/tlpkg-ctan-check
@@ -366,7 +366,7 @@ my @TLP_working = qw(
tex-ewd tex-font-errors-cheatsheet tex-gyre tex-label tex-overview
texapi texcount
texdef texdiff texdirflatten texilikechaps texilikecover
- texloganalyser texlogos texmate texments
+ texliveonfly texloganalyser texlogos texmate texments
texpower texshade
textcase textfit textgreek textmerg textopo textpath textpos tfrupee
thailatex theoremref thesis-titlepage-fhac
diff --git a/Master/tlpkg/libexec/ctan2tds b/Master/tlpkg/libexec/ctan2tds
index e8da2089e88..62db10f066f 100755
--- a/Master/tlpkg/libexec/ctan2tds
+++ b/Master/tlpkg/libexec/ctan2tds
@@ -2017,6 +2017,7 @@ $standardxmt='\.xmt';
'texdef' => '\.pl$',
'texdiff' => 'texdiff$',
'texdirflatten' => 'texdirflatten$',
+ 'texliveonfly' => '\.py$',
'texloganalyser' => 'texloganalyser',
'thumbpdf' => '\.pl$',
'ulqda' => '\.pl$',
diff --git a/Master/tlpkg/tlpsrc/collection-binextra.tlpsrc b/Master/tlpkg/tlpsrc/collection-binextra.tlpsrc
index bfc70651bbf..c7a083fa2f3 100644
--- a/Master/tlpkg/tlpsrc/collection-binextra.tlpsrc
+++ b/Master/tlpkg/tlpsrc/collection-binextra.tlpsrc
@@ -52,6 +52,7 @@ depend texdef
depend texdiff
depend texdirflatten
depend texdoc
+depend texliveonfly
depend texloganalyser
depend texware
depend tie
diff --git a/Master/tlpkg/tlpsrc/texliveonfly.tlpsrc b/Master/tlpkg/tlpsrc/texliveonfly.tlpsrc
new file mode 100644
index 00000000000..d8e8088eefc
--- /dev/null
+++ b/Master/tlpkg/tlpsrc/texliveonfly.tlpsrc
@@ -0,0 +1 @@
+binpattern f bin/${ARCH}/texliveonfly