From 304d443084c947877cec2ad993a8cd7ffb5d9db8 Mon Sep 17 00:00:00 2001 From: Thomas Schouten Date: Sat, 1 Jun 2024 20:50:12 +0200 Subject: [PATCH 1/2] Index files in texinputs --- .../file/LatexIndexableSetContributor.kt | 4 ++ .../reference/InputFileReference.kt | 34 +---------- .../texifyidea/util/LatexmkRcFileFinder.kt | 17 +++--- .../texifyidea/util/SystemEnvironment.kt | 59 +++++++++++++++++++ 4 files changed, 71 insertions(+), 43 deletions(-) diff --git a/src/nl/hannahsten/texifyidea/index/file/LatexIndexableSetContributor.kt b/src/nl/hannahsten/texifyidea/index/file/LatexIndexableSetContributor.kt index f6d31a06e..80aa88f49 100644 --- a/src/nl/hannahsten/texifyidea/index/file/LatexIndexableSetContributor.kt +++ b/src/nl/hannahsten/texifyidea/index/file/LatexIndexableSetContributor.kt @@ -4,11 +4,13 @@ import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.progress.Task.Backgroundable import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.LocalFileSystem import com.intellij.openapi.vfs.VirtualFile import com.intellij.util.indexing.IndexableSetContributor import nl.hannahsten.texifyidea.settings.TexifySettings import nl.hannahsten.texifyidea.settings.sdk.LatexSdkUtil import nl.hannahsten.texifyidea.util.Log +import nl.hannahsten.texifyidea.util.getTexinputsPaths import nl.hannahsten.texifyidea.util.isTestProject import org.codehaus.plexus.archiver.ArchiverException import org.codehaus.plexus.archiver.tar.TarBZip2UnArchiver @@ -58,6 +60,8 @@ class LatexIndexableSetContributor : IndexableSetContributor() { // Unfortunately, since .sty is a LaTeX file type, these will all be parsed, which will take an enormous amount of time. // Note that using project-independent getAdditionalRootsToIndex does not fix this roots.addAll(LatexSdkUtil.getSdkSourceRoots(project) { sdkType, homePath -> sdkType.getDefaultStyleFilesPath(homePath) }) + + roots.addAll(getTexinputsPaths(project, rootFiles = listOf(), expandPaths = false).mapNotNull { LocalFileSystem.getInstance().findFileByPath(it) }) Log.debug("Indexing source roots $roots") return roots diff --git a/src/nl/hannahsten/texifyidea/reference/InputFileReference.kt b/src/nl/hannahsten/texifyidea/reference/InputFileReference.kt index be2fa6c88..be828074e 100644 --- a/src/nl/hannahsten/texifyidea/reference/InputFileReference.kt +++ b/src/nl/hannahsten/texifyidea/reference/InputFileReference.kt @@ -1,7 +1,5 @@ package nl.hannahsten.texifyidea.reference -import com.intellij.execution.RunManager -import com.intellij.execution.impl.RunManagerImpl import com.intellij.openapi.roots.ProjectRootManager import com.intellij.openapi.util.TextRange import com.intellij.openapi.vfs.LocalFileSystem @@ -15,12 +13,10 @@ import nl.hannahsten.texifyidea.completion.pathcompletion.LatexGraphicsPathProvi import nl.hannahsten.texifyidea.lang.commands.LatexGenericRegularCommand import nl.hannahsten.texifyidea.psi.LatexCommands import nl.hannahsten.texifyidea.psi.LatexPsiHelper -import nl.hannahsten.texifyidea.run.latex.LatexRunConfiguration import nl.hannahsten.texifyidea.settings.sdk.LatexSdkUtil import nl.hannahsten.texifyidea.util.* import nl.hannahsten.texifyidea.util.files.* import nl.hannahsten.texifyidea.util.magic.CommandMagic -import java.io.File /** * Reference to a file, based on the command and the range of the filename within the command text. @@ -40,10 +36,6 @@ class InputFileReference( companion object { - private val texinputs by lazy { - runCommand("kpsewhich", "--expand-var", "'\$TEXINPUTS'") - } - /** * Handle element rename, but taking into account whether the given * newElementName is just a filename which we have to replace, @@ -123,31 +115,7 @@ class InputFileReference( val rootDirectories = rootFiles.mapNotNull { it.parent } // Check environment variables - val runManager = RunManagerImpl.getInstanceImpl(element.project) as RunManager - val texinputsVariable = runManager.allConfigurationsList - .filterIsInstance() - .firstOrNull { it.mainFile in rootFiles } - ?.environmentVariables - ?.envs - ?.getOrDefault("TEXINPUTS", null) - // Not sure which of these takes precedence, or if they are joined together - ?: LatexmkRcFileFinder.getTexinputsVariable(element.containingFile, null) - ?: texinputs - - for (texInputPath in texinputsVariable?.trim('\'')?.split(File.pathSeparator)?.filter { it.isNotBlank() } ?: emptyList()) { - val path = texInputPath.trimEnd(File.pathSeparatorChar) - searchPaths.add(path.trimEnd('/')) - // See the kpathsea manual, // expands to subdirs - if (path.endsWith("//")) { - LocalFileSystem.getInstance().findFileByPath(path.trimEnd('/'))?.let { parent -> - searchPaths.addAll( - parent.allChildDirectories() - .filter { it.isDirectory } - .map { it.path } - ) - } - } - } + searchPaths += getTexinputsPaths(element.project, rootFiles, expandPaths = true, latexmkSearchDirectory = element.containingFile?.virtualFile?.parent) // BIBINPUTS // Not used for building the fileset, so we can use the fileset to lookup the BIBINPUTS environment variable diff --git a/src/nl/hannahsten/texifyidea/util/LatexmkRcFileFinder.kt b/src/nl/hannahsten/texifyidea/util/LatexmkRcFileFinder.kt index 6096a13ff..4634738ba 100644 --- a/src/nl/hannahsten/texifyidea/util/LatexmkRcFileFinder.kt +++ b/src/nl/hannahsten/texifyidea/util/LatexmkRcFileFinder.kt @@ -1,11 +1,11 @@ package nl.hannahsten.texifyidea.util import com.intellij.openapi.progress.ProcessCanceledException +import com.intellij.openapi.project.Project import com.intellij.openapi.project.guessProjectDir import com.intellij.openapi.util.SystemInfo import com.intellij.openapi.vfs.LocalFileSystem import com.intellij.openapi.vfs.VirtualFile -import com.intellij.psi.PsiFile import nl.hannahsten.texifyidea.run.compiler.LatexCompiler import nl.hannahsten.texifyidea.run.latex.LatexRunConfiguration import java.io.File @@ -116,12 +116,12 @@ object LatexmkRcFileFinder { * Get the first TEXINPUTS we can find in latexmkrc files. * Cached because searching involves quite some system calls, and it's a rarely used feature. */ - fun getTexinputsVariable(someFile: PsiFile?, runConfig: LatexRunConfiguration?): String? { + fun getTexinputsVariable(directory: VirtualFile, runConfig: LatexRunConfiguration?, project: Project): String? { return if (usesLatexmkrc == false) { null } else { - val texinputs = getTexinputsVariableNoCache(someFile, runConfig) + val texinputs = getTexinputsVariableNoCache(directory, runConfig, project) if (usesLatexmkrc == null) { usesLatexmkrc = texinputs != null } @@ -132,20 +132,17 @@ object LatexmkRcFileFinder { /** * Check the (first) latexmkrc file for any additions to TEXINPUTS and return that if present. * - * @param someFile Any file, the parent directories will be searched. * @param runConfig Run configuration to check for working directory and arguments. */ - private fun getTexinputsVariableNoCache(someFile: PsiFile?, runConfig: LatexRunConfiguration?): String? { + private fun getTexinputsVariableNoCache(directory: VirtualFile, runConfig: LatexRunConfiguration?, project: Project): String? { systemLatexmkRcFile?.let { return getTexinputs(it) } if (runConfig != null) { getLocalLatexmkRcFile(runConfig.compilerArguments, runConfig.mainFile?.parent?.path)?.let { return getTexinputs(it) } } // File could be anywhere if run configurations are not used, but searching the whole project could be too expensive - someFile?.virtualFile?.parent?.let { parentDir -> - parentDir.findChild(".latexmkrc")?.let { return getTexinputs(it) } - parentDir.findChild("latexmkrc")?.let { return getTexinputs(it) } - } - val project = someFile?.project ?: return null + directory.findChild(".latexmkrc")?.let { return getTexinputs(it) } + directory.findChild("latexmkrc")?.let { return getTexinputs(it) } + val projectDir = project.guessProjectDir() if (projectDir?.isValid == false) return null projectDir?.findChild(".latexmkrc")?.let { return getTexinputs(it) } diff --git a/src/nl/hannahsten/texifyidea/util/SystemEnvironment.kt b/src/nl/hannahsten/texifyidea/util/SystemEnvironment.kt index 6074a9644..cd55d0bfd 100644 --- a/src/nl/hannahsten/texifyidea/util/SystemEnvironment.kt +++ b/src/nl/hannahsten/texifyidea/util/SystemEnvironment.kt @@ -1,8 +1,16 @@ package nl.hannahsten.texifyidea.util +import com.intellij.execution.RunManager import com.intellij.execution.configurations.GeneralCommandLine +import com.intellij.execution.impl.RunManagerImpl import com.intellij.execution.process.ProcessNotCreatedException +import com.intellij.openapi.project.Project +import com.intellij.openapi.project.guessProjectDir import com.intellij.openapi.util.SystemInfo +import com.intellij.openapi.vfs.LocalFileSystem +import com.intellij.openapi.vfs.VirtualFile +import nl.hannahsten.texifyidea.run.latex.LatexRunConfiguration +import nl.hannahsten.texifyidea.util.files.* import org.apache.maven.artifact.versioning.DefaultArtifactVersion import java.io.File import java.io.IOException @@ -53,6 +61,10 @@ class SystemEnvironment { val evinceVersion: DefaultArtifactVersion by lazy { DefaultArtifactVersion("evince --version".runCommand()?.split(" ")?.lastOrNull() ?: "") } + + val texinputs by lazy { + runCommand("kpsewhich", "--expand-var", "'\$TEXINPUTS'") + } } } @@ -146,3 +158,50 @@ private fun readInputStream(nonBlocking: Boolean, proc: Process): String { } return output } + +/** + * Collect texinputs from various places + * + * @param rootFiles If provided, filter run configurations + * @param expandPaths Expand subdirectories + */ +fun getTexinputsPaths( + project: Project, + rootFiles: Collection, + expandPaths: Boolean = true, + latexmkSearchDirectory: VirtualFile? = null +): List { + val searchPaths = mutableListOf() + val runManager = RunManagerImpl.getInstanceImpl(project) as RunManager + val allConfigurations = runManager.allConfigurationsList + .filterIsInstance() + val selectedConfiguratios = if (rootFiles.isEmpty()) allConfigurations else allConfigurations.filter { it.mainFile in rootFiles } + val configurationTexinputsVariables = selectedConfiguratios.map { it.environmentVariables.envs }.mapNotNull { it.getOrDefault("TEXINPUTS", null) } + // Not sure which of these takes precedence, or if they are joined together + val texinputsVariables = configurationTexinputsVariables + + selectedConfiguratios.map { LatexmkRcFileFinder.getTexinputsVariable(latexmkSearchDirectory ?: project.guessProjectDir() ?: return@map null, it, project) } + + listOf(if (expandPaths) SystemEnvironment.texinputs else System.getenv("TEXINPUTS")) + + for (texinputsVariable in texinputsVariables.filterNotNull()) { + for (texInputPath in texinputsVariable.trim('\'').split(File.pathSeparator).filter { it.isNotBlank() }) { + val path = texInputPath.trimEnd(File.pathSeparatorChar) + searchPaths.add(path.trimEnd('/')) + // See the kpathsea manual, // expands to subdirs + if (path.endsWith("//")) { + LocalFileSystem.getInstance().findFileByPath(path.trimEnd('/'))?.let { parent -> + if (expandPaths) { + searchPaths.addAll( + parent.allChildDirectories() + .filter { it.isDirectory } + .map { it.path } + ) + } + else { + searchPaths.add(parent.path) + } + } + } + } + } + return searchPaths +} From b284a87c3e173ba737b7f936c7bc67bf49da288c Mon Sep 17 00:00:00 2001 From: Thomas Schouten Date: Thu, 6 Jun 2024 08:13:18 +0200 Subject: [PATCH 2/2] 0.9.7-alpha.1 --- CHANGELOG.md | 11 ++++++++++- gradle.properties | 2 +- resources/META-INF/actions/actions.xml | 2 +- .../texifyidea/action/analysis/WordCountAction.kt | 3 +++ .../hannahsten/texifyidea/util/LatexmkRcFileFinder.kt | 6 +++--- 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0fc575a4..80d03d4e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,14 @@ ### Fixed +## [0.9.7-alpha.1] - 2024-06-06 + +### Added + +* Support TeX Live docker image +* Formatter support for plain TeX \if-statements +* Index files from the TEXINPUTS variable, for autocompletion + ## [0.9.6] - 2024-06-01 Welcome to TeXiFy IDEA 0.9.6! This release fixes an issue with the table insertion wizard, fixes pasting from a pdf file, and more. @@ -358,7 +366,8 @@ Thanks to @jojo2357 and @MisterDeenis for contributing to this release! * Fix some intention previews. ([#2796](https://github.com/Hannah-Sten/TeXiFy-IDEA/issues/2796)) * Other small bug fixes and improvements. ([#2776](https://github.com/Hannah-Sten/TeXiFy-IDEA/issues/2776), [#2774](https://github.com/Hannah-Sten/TeXiFy-IDEA/issues/2774), [#2765](https://github.com/Hannah-Sten/TeXiFy-IDEA/issues/2765)-[#2773](https://github.com/Hannah-Sten/TeXiFy-IDEA/issues/2773)) -[Unreleased]: https://github.com/Hannah-Sten/TeXiFy-IDEA/compare/v0.9.6...HEAD +[Unreleased]: https://github.com/Hannah-Sten/TeXiFy-IDEA/compare/v0.9.7-alpha.1...HEAD +[0.9.7-alpha.1]: https://github.com/Hannah-Sten/TeXiFy-IDEA/compare/v0.9.6...v0.9.7-alpha.1 [0.9.6]: https://github.com/Hannah-Sten/TeXiFy-IDEA/compare/v0.9.5...v0.9.6 [0.9.5]: https://github.com/Hannah-Sten/TeXiFy-IDEA/compare/v0.9.4...v0.9.5 [0.9.4]: https://github.com/Hannah-Sten/TeXiFy-IDEA/compare/v0.9.3...v0.9.4 diff --git a/gradle.properties b/gradle.properties index 5c711d0d8..e1be4a480 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -pluginVersion = 0.9.6 +pluginVersion = 0.9.7-alpha.1 # Info about build ranges: https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html # Note that an xyz branch corresponds to version 20xy.z and a since build of xyz.* diff --git a/resources/META-INF/actions/actions.xml b/resources/META-INF/actions/actions.xml index 8570b1e04..db3500a9d 100644 --- a/resources/META-INF/actions/actions.xml +++ b/resources/META-INF/actions/actions.xml @@ -18,7 +18,7 @@ - + diff --git a/src/nl/hannahsten/texifyidea/action/analysis/WordCountAction.kt b/src/nl/hannahsten/texifyidea/action/analysis/WordCountAction.kt index 260b58368..a278f7814 100644 --- a/src/nl/hannahsten/texifyidea/action/analysis/WordCountAction.kt +++ b/src/nl/hannahsten/texifyidea/action/analysis/WordCountAction.kt @@ -4,6 +4,7 @@ import com.intellij.icons.AllIcons import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.PlatformDataKeys +import com.intellij.openapi.fileEditor.FileDocumentManager import com.intellij.openapi.ui.DialogBuilder import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile @@ -71,6 +72,8 @@ open class WordCountAction : AnAction() { // Prefer texcount, I think it is slightly more accurate val dialog = if (SystemEnvironment.isAvailable("texcount")) { val root = psiFile.findRootFile().virtualFile + // Make sure the file is written to disk before running an external tool on it + FileDocumentManager.getInstance().apply { saveDocument(getDocument(root) ?: return@apply) } val (output, exitCode) = runCommandWithExitCode("texcount", "-1", "-inc", "-sum", root.name, workingDirectory = File(root.parent.path)) if (exitCode == 0 && output?.toIntOrNull() != null) { makeDialog(psiFile, output.toInt()) diff --git a/src/nl/hannahsten/texifyidea/util/LatexmkRcFileFinder.kt b/src/nl/hannahsten/texifyidea/util/LatexmkRcFileFinder.kt index 4634738ba..79ed36db2 100644 --- a/src/nl/hannahsten/texifyidea/util/LatexmkRcFileFinder.kt +++ b/src/nl/hannahsten/texifyidea/util/LatexmkRcFileFinder.kt @@ -147,9 +147,9 @@ object LatexmkRcFileFinder { if (projectDir?.isValid == false) return null projectDir?.findChild(".latexmkrc")?.let { return getTexinputs(it) } projectDir?.findChild("latexmkrc")?.let { return getTexinputs(it) } - projectDir?.children?.forEach { directory -> - directory?.findChild(".latexmkrc")?.let { return getTexinputs(it) } - directory?.findChild("latexmkrc")?.let { return getTexinputs(it) } + projectDir?.children?.forEach { childDir -> + childDir?.findChild(".latexmkrc")?.let { return getTexinputs(it) } + childDir?.findChild("latexmkrc")?.let { return getTexinputs(it) } } return null }