Skip to content
Permalink
Browse files

Merge pull request #5490 from rstudio/feature/tinytex-support

add support for installing tinytex
  • Loading branch information
kevinushey committed Oct 9, 2019
2 parents db4fdb8 + dbb6c68 commit 2d8c683d0c97e665efdf1ff4896486e77f783458
@@ -31,16 +31,22 @@ namespace xdg {
* All of these can be configured with environment variables as described below.
*/

// Returns the RStudio XDG user config directory. On Unix-alikes, this is ~/.config/rstudio, or
// XDG_CONFIG_HOME.
// Returns the RStudio XDG user config directory.
//
// On Unix-alikes, this is ~/.config/rstudio, or XDG_CONFIG_HOME.
// On Windows, this is 'FOLDERID_RoamingAppData' (typically 'AppData/Roaming').
FilePath userConfigDir();

// Returns the RStudio XDG user data directory. On Unix-alikes, this is ~/.local/share/rstudio, or
// XDG_DATA_HOME
// Returns the RStudio XDG user data directory.
//
// On Unix-alikes, this is ~/.local/share/rstudio, or XDG_DATA_HOME.
// On Windows, this is 'FOLDERID_LocalAppData' (typically 'AppData/Local').
FilePath userDataDir();

// Returns the RStudio XDG system config directory. On Unix-alikes, this is /etc/rstudio, or
// XDG_CONFIG_DIRS
// Returns the RStudio XDG system config directory.
//
// On Unix-alikes, this is /etc/rstudio, XDG_CONFIG_DIRS.
// On Windows, this is 'FOLDERID_ProgramData' (typically 'C:/ProgramData').
FilePath systemConfigDir();

} // namespace xdg
@@ -1077,9 +1077,35 @@ FilePath findProgram(const std::string& name)
}
}

bool addTinytexToPathIfNecessary()
{
// avoid some pathological cases where e.g. TinyTeX folder
// exists but doesn't have the pdflatex binary (don't
// attempt to re-add the folder multiple times)
static bool s_added = false;
if (s_added)
return true;

if (!module_context::findProgram("pdflatex").empty())
return false;

std::string binDir;
Error error = r::exec::RFunction(".rs.tinytexBin").call(&binDir);
if (error)
LOG_ERROR(error);

FilePath binPath = module_context::resolveAliasedPath(binDir);
if (!binPath.exists())
return false;

s_added = true;
core::system::addToSystemPath(binPath);
return true;
}

bool isPdfLatexInstalled()
{
addTinytexToPathIfNecessary();
return !module_context::findProgram("pdflatex").empty();
}

@@ -118,6 +118,7 @@ std::string rLibsUser();
// find out the location of a binary
core::FilePath findProgram(const std::string& name);

bool addTinytexToPathIfNecessary();
bool isPdfLatexInstalled();

// is the file a text file
@@ -462,4 +462,31 @@
FALSE
})

.rs.addFunction("tinytexRoot", function()
{
sysname <- Sys.info()[["sysname"]]
if (sysname == "Windows")
file.path(Sys.getenv("APPDATA"), "TinyTeX")
else if (sysname == "Darwin")
"~/Library/TinyTeX"
else
"~/.TinyTeX"
})

.rs.addFunction("tinytexBin", function()
{
root <- tryCatch(
tinytex:::tinytex_root(),
error = function(e) .rs.tinytexRoot()
)

if (!file.exists(root))
return(NULL)

# NOTE: binary directory has a single arch-specific subdir;
# rather than trying to hard-code the architecture we just
# infer it directly
bin <- file.path(root, "bin")
subbin <- list.files(bin, full.names = TRUE)
normalizePath(subbin[[1]], mustWork = TRUE)
})
@@ -596,6 +596,9 @@ class AsyncPdfCompiler : boost::noncopyable,
if (error)
LOG_ERROR(error);

// add tinytex to the PATH if appropriate
module_context::addTinytexToPathIfNecessary();

// determine tex program path
std::string userErrMsg;
if (!pdflatex::latexProgramForFile(magicComments_,
@@ -142,6 +142,14 @@ else if (n == 3)
}));
}

public void showTexInstallationMissingWarning(String message,
Command onInstall)
{
setText(message);
labelRight_.clear();
labelRight_.add(label("Install TinyTeX", () -> { onInstall.execute(); }));
}

public void showReadOnlyWarning(List<String> alternatives)
{
if (alternatives.size() == 0)
@@ -484,6 +484,20 @@ public void withStan(final String progressCaption,
(Boolean success) -> { if (success) command.execute(); });
}

public void withTinyTeX(final String progressCaption,
final String userPrompt,
final Command command)
{
withDependencies(
progressCaption,
userPrompt,
new Dependency[] {
Dependency.cranPackage("tinytex", "0.16")
},
true,
(Boolean success) -> { if (success) command.execute(); });
}

@Override
public void onPackageStateChanged(PackageStateChangedEvent event)
{
@@ -315,6 +315,12 @@ public void showRequiredPackagesMissingWarning(List<String> packages)
// no-op for code browser targets
}

@Override
public void showTexInstallationMissingWarning(String message)
{
// no-op for code browser targets
}

@Override
public void showWarningBar(final String warning)
{
@@ -1252,6 +1252,24 @@ public void showRequiredPackagesMissingWarning(List<String> packages)
view_.showRequiredPackagesMissingWarning(packages);
}

public void showTexInstallationMissingWarning(String message)
{
view_.showTexInstallationMissingWarning(message);
}

public void installTinyTeX()
{
Command onInstall = () -> {
String code = "tinytex::install_tinytex()";
events_.fireEvent(new SendToConsoleEvent(code, true));
};

dependencyManager_.withTinyTeX(
"Installing tinytex",
"Installing TinyTeX",
onInstall);
}

private void jumpToPreviousFunction()
{
Scope jumpTo = scopeHelper_.getPreviousFunction(
@@ -215,12 +215,12 @@ public void onResponseReceived(TexCapabilities response)
{
String warning;
if (Desktop.isDesktop())
warning = "No TeX installation detected. Please install " +
"TeX before compiling.";
warning = "No LaTeX installation detected. Please install " +
"LaTeX before compiling.";
else
warning = "This server does not have TeX installed. You " +
warning = "This server does not have LaTeX installed. You " +
"may not be able to compile.";
display.showWarningBar(warning);
display.showTexInstallationMissingWarning(warning);
}
else if (checkForRnwWeave &&
!response.isRnwWeaveAvailable(fRnwWeave))
@@ -901,6 +901,19 @@ public void showRequiredPackagesMissingWarning(List<String> packages)
showWarningImpl(() -> warningBar_.showRequiredPackagesMissingWarning(packages, onInstall, onDismiss));
}

@Override
public void showTexInstallationMissingWarning(String message)
{
final Command install = () -> {
target_.installTinyTeX();
hideWarningBar();
};

showWarningImpl(() -> {
warningBar_.showTexInstallationMissingWarning(message, install);
});
}

@Override
public void showWarningBar(final String warning)
{
@@ -22,6 +22,7 @@
{
void showReadOnlyWarning(List<String> alternatives);
void showRequiredPackagesMissingWarning(List<String> packages);
void showTexInstallationMissingWarning(String message);
void showWarningBar(String message);
void hideWarningBar();
}

0 comments on commit 2d8c683

Please sign in to comment.
You can’t perform that action at this time.