Skip to content

Commit

Permalink
Use IJ Platform infrastructure for executing processes
Browse files Browse the repository at this point in the history
  • Loading branch information
FirstTimeInForever committed Mar 23, 2021
1 parent 16ebec0 commit 57d6763
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 77 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.firsttimeinforever.intellij.pdf.viewer.tex

import com.firsttimeinforever.intellij.pdf.viewer.util.CommandExecutionUtils
import com.intellij.execution.configurations.GeneralCommandLine
import com.intellij.openapi.vfs.VirtualFile

object SynctexUtils {
/**
* Checks if there is a SyncTeX file in the same folder as [this] file,
* with the same base name (until the first period).
* When there is no such SyncTeX file, all SyncTeX features should be disabled.
*
* Call this function on a pdf file to check if it has an accompanying SyncTeX file in the same folder.
*/
fun VirtualFile.isSynctexFileAvailable(): Boolean {
return parent.children
.filter { it.name.contains("synctex") }
.any { file ->
file.name.takeWhile { it != '.' } == name.takeWhile { it != '.' }
}
}

/**
* Check if the SyncTeX command line utility is installed by trying to execute a SyncTeX command.
*/
fun isSynctexInstalled(): Boolean {
val output = CommandExecutionUtils.runCommand(GeneralCommandLine("synctex", "version")) ?: return false
return output.stdout.contains("This is SyncTeX command line utility") ||
output.stderr.contains("This is SyncTeX command line utility")
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package com.firsttimeinforever.intellij.pdf.viewer.tex

import com.firsttimeinforever.intellij.pdf.viewer.ui.editor.panel.jcef.events.objects.SynctexInverseDataObject
import com.firsttimeinforever.intellij.pdf.viewer.util.runCommand
import com.firsttimeinforever.intellij.pdf.viewer.util.CommandExecutionUtils.getCommandStdoutIfSuccessful
import com.intellij.execution.configurations.GeneralCommandLine
import com.intellij.openapi.application.runInEdt
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.fileEditor.OpenFileDescriptor
Expand All @@ -17,7 +18,6 @@ import java.io.File
* aka inverse or backward search.
*/
class TexFileInfo(val file: VirtualFile, private val line: Int, private val column: Int) {

/**
* Use SyncTeX to open the corresponding tex [file] at [line] and [column].
*
Expand Down Expand Up @@ -64,16 +64,17 @@ class TexFileInfo(val file: VirtualFile, private val line: Int, private val colu
fun fromSynctexInfoData(pdfFile: VirtualFile, data: SynctexInverseDataObject): TexFileInfo? {
// Use presentableUrl instead of path to get a valid Windows path (with backslashes instead of forward slashes).
val pdfDir = File(pdfFile.parent.presentableUrl)

val command = arrayOf(
"synctex", "edit", "-o", "${data.page}:${data.x}:${data.y}:${pdfFile.presentableUrl}",
)
val synctexOutput = runCommand(*command, directory = pdfDir) ?: return null
println(synctexOutput)
val texPath = INPUT_REGEX.find(synctexOutput)?.groups?.get("file")?.value ?: return null
val line = LINE_REGEX.find(synctexOutput)?.groups?.get("line")?.value?.toInt() ?: 1
val column = COLUMN_REGEX.find(synctexOutput)?.groups?.get("col")?.value?.toInt() ?: 1

val command = GeneralCommandLine(
"synctex",
"edit",
"-o",
"${data.page}:${data.x}:${data.y}:${pdfFile.presentableUrl}"
).withWorkDirectory(pdfDir)
val output = getCommandStdoutIfSuccessful(command) ?: return null
println(output)
val texPath = INPUT_REGEX.find(output)?.groups?.get("file")?.value ?: return null
val line = LINE_REGEX.find(output)?.groups?.get("line")?.value?.toInt() ?: 1
val column = COLUMN_REGEX.find(output)?.groups?.get("col")?.value?.toInt() ?: 1
val texFile = LocalFileSystem.getInstance().findFileByPath(texPath.trim()) ?: return null
return TexFileInfo(texFile, line, column)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ package com.firsttimeinforever.intellij.pdf.viewer.tex

import com.firsttimeinforever.intellij.pdf.viewer.ui.editor.PdfFileEditor
import com.firsttimeinforever.intellij.pdf.viewer.ui.editor.panel.jcef.events.objects.SynctexFowardDataObject
import com.firsttimeinforever.intellij.pdf.viewer.util.isSynctexInstalled
import com.firsttimeinforever.intellij.pdf.viewer.util.runCommand
import com.firsttimeinforever.intellij.pdf.viewer.util.CommandExecutionUtils.getCommandStdoutIfSuccessful
import com.intellij.execution.configurations.GeneralCommandLine
import com.intellij.ide.actions.OpenInRightSplitAction
import com.intellij.notification.Notification
import com.intellij.notification.NotificationType
import com.intellij.notification.Notifications
import com.intellij.openapi.application.invokeLater
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.fileEditor.OpenFileDescriptor
Expand Down Expand Up @@ -43,7 +42,7 @@ class TexPdfViewer : ExternalPdfViewer {
project: Project,
focusAllowed: Boolean
) {
if (!isSynctexInstalled()) {
if (!SynctexUtils.isSynctexInstalled()) {
Notification(
"LaTeX",
"SyncTeX not installed",
Expand Down Expand Up @@ -78,9 +77,16 @@ class TexPdfViewer : ExternalPdfViewer {
editorWindow?.selectedEditor?.selectedWithProvider?.fileEditor as PdfFileEditor
}

val command = arrayOf("synctex", "view", "-i", "$line:0:${texFile.path}", "-o", file.path)
val synctexOutput = runCommand(*command, directory = File(file.parent.path)) ?: return@invokeLater
val values: Map<String?, String?> = NUMBER_REGEX.findAll(synctexOutput)
val command = GeneralCommandLine(
"synctex",
"view",
"-i",
"$line:0:${texFile.path}",
"-o",
file.path
).withWorkDirectory(File(file.parent.path))
val output = getCommandStdoutIfSuccessful(command) ?: return@invokeLater
val values: Map<String?, String?> = NUMBER_REGEX.findAll(output)
.associate { it.groups["id"]?.value to it.groups["value"]?.value }
.filter { it.key != null && it.value != null }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ package com.firsttimeinforever.intellij.pdf.viewer.ui.editor.panel.jcef

import com.firsttimeinforever.intellij.pdf.viewer.PdfViewerBundle
import com.firsttimeinforever.intellij.pdf.viewer.settings.PdfViewerSettings
import com.firsttimeinforever.intellij.pdf.viewer.tex.TexFileInfo
import com.firsttimeinforever.intellij.pdf.viewer.settings.PdfViewerSettingsListener
import com.firsttimeinforever.intellij.pdf.viewer.tex.SynctexUtils.isSynctexFileAvailable
import com.firsttimeinforever.intellij.pdf.viewer.tex.SynctexUtils.isSynctexInstalled
import com.firsttimeinforever.intellij.pdf.viewer.tex.TexFileInfo
import com.firsttimeinforever.intellij.pdf.viewer.ui.editor.StaticServer
import com.firsttimeinforever.intellij.pdf.viewer.ui.editor.panel.PdfFileEditorPanel
import com.firsttimeinforever.intellij.pdf.viewer.ui.editor.panel.jcef.events.MessageEventReceiver
import com.firsttimeinforever.intellij.pdf.viewer.ui.editor.panel.jcef.events.MessageEventSender
import com.firsttimeinforever.intellij.pdf.viewer.ui.editor.panel.jcef.events.SubscribableEventType
import com.firsttimeinforever.intellij.pdf.viewer.ui.editor.panel.jcef.events.TriggerableEventType
import com.firsttimeinforever.intellij.pdf.viewer.ui.editor.panel.jcef.events.objects.*
import com.firsttimeinforever.intellij.pdf.viewer.util.isSynctexFileAvailable
import com.firsttimeinforever.intellij.pdf.viewer.util.isSynctexInstalled
import com.intellij.notification.Notification
import com.intellij.notification.NotificationType
import com.intellij.notification.Notifications
Expand All @@ -28,13 +28,15 @@ import com.intellij.openapi.project.DumbAware
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.DialogBuilder
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.vfs.*
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.openapi.vfs.newvfs.BulkFileListener
import com.intellij.openapi.vfs.newvfs.events.VFileEvent
import com.intellij.ui.jcef.JCEFHtmlPanel
import com.intellij.util.ui.UIUtil
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.*
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.encodeToJsonElement
import org.cef.browser.CefBrowser
import org.cef.browser.CefFrame
import org.cef.handler.CefLoadHandlerAdapter
Expand Down Expand Up @@ -267,7 +269,10 @@ class PdfFileEditorJcefPanel(project: Project, virtualFile: VirtualFile):
updatePageNumber(currentPageNumber)
setThemeColors()
setScale(currentScaleValue)
eventSender.triggerWith(TriggerableEventType.SET_SYNCTEX_AVAILABLE, virtualFile.isSynctexFileAvailable() && isSynctexInstalled())
eventSender.triggerWith(
TriggerableEventType.SET_SYNCTEX_AVAILABLE,
virtualFile.isSynctexFileAvailable() && isSynctexInstalled()
)
}
}, browserPanel.cefBrowser)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.firsttimeinforever.intellij.pdf.viewer.util

import com.intellij.execution.ExecutionException
import com.intellij.execution.configurations.GeneralCommandLine
import com.intellij.execution.process.ProcessOutput
import com.intellij.execution.util.ExecUtil
import com.intellij.openapi.application.ApplicationManager

internal object CommandExecutionUtils {
fun runCommand(commandLine: GeneralCommandLine): ProcessOutput? {
return ApplicationManager.getApplication().executeOnPooledThread<ProcessOutput?> {
try {
ExecUtil.execAndGetOutput(commandLine, timeoutInMilliseconds = 3000)
} catch (exception: ExecutionException) {
exception.printStackTrace()
null
}
}.get()
}

fun getCommandStdoutIfSuccessful(commandLine: GeneralCommandLine): String? {
return runCommand(commandLine)?.let {
when (it.exitCode) {
0 -> it.stdout
else -> null
}
}
}
}

This file was deleted.

This file was deleted.

0 comments on commit 57d6763

Please sign in to comment.