Skip to content

Commit

Permalink
Merge pull request #4387 from akenejie/master
Browse files Browse the repository at this point in the history
Support tap PDF to move to LaTeX on remote file system
  • Loading branch information
James-Yu authored Oct 5, 2024
2 parents c6cbb8d + e4a9c49 commit 1f3b9c5
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 115 deletions.
4 changes: 2 additions & 2 deletions src/compile/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -425,9 +425,9 @@ async function afterSuccessfulBuilt(lastStep: Step, skipped: boolean) {
const configuration = vscode.workspace.getConfiguration('latex-workshop', vscode.Uri.file(lastStep.rootFile))
// If the PDF viewer is internal, we call SyncTeX in src/components/viewer.ts.
if (configuration.get('view.pdf.viewer') === 'external' && configuration.get('synctex.afterBuild.enabled')) {
const pdfFile = lw.file.getPdfPath(lastStep.rootFile)
const pdfUri = vscode.Uri.file(lw.file.getPdfPath(lastStep.rootFile))
logger.log('SyncTex after build invoked.')
lw.locate.synctex.toPDF(pdfFile)
lw.locate.synctex.toPDF(pdfUri)
}
if (['onSucceeded', 'onBuilt'].includes(configuration.get('latex.autoClean.run') as string)) {
logger.log('Auto Clean invoked.')
Expand Down
10 changes: 5 additions & 5 deletions src/core/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export async function view(mode?: 'tab' | 'browser' | 'external' | vscode.Uri) {
if (!pickedRootFile) {
return
}
return lw.viewer.view(lw.file.getPdfPath(pickedRootFile), typeof mode === 'string' ? mode : undefined)
return lw.viewer.view(vscode.Uri.file(lw.file.getPdfPath(pickedRootFile)), typeof mode === 'string' ? mode : undefined)
}

export function refresh() {
Expand All @@ -93,13 +93,13 @@ export function synctex() {
return
}
const configuration = vscode.workspace.getConfiguration('latex-workshop', lw.root.getWorkspace())
let pdfFile: string | undefined = undefined
let pdfUri: vscode.Uri | undefined = undefined
if (lw.root.subfiles.path && configuration.get('latex.rootFile.useSubFile')) {
pdfFile = lw.file.getPdfPath(lw.root.subfiles.path)
pdfUri = vscode.Uri.file(lw.file.getPdfPath(lw.root.subfiles.path))
} else if (lw.root.file.path !== undefined) {
pdfFile = lw.file.getPdfPath(lw.root.file.path)
pdfUri = vscode.Uri.file(lw.file.getPdfPath(lw.root.file.path))
}
lw.locate.synctex.toPDF(pdfFile)
lw.locate.synctex.toPDF(pdfUri)
}

export function synctexonref(line: number, filePath: string) {
Expand Down
46 changes: 23 additions & 23 deletions src/locate/synctex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,14 +182,14 @@ function parseToPDFList(result: string): SyncTeXRecordToPDFAll[] {
* document and cursor position. The forward SyncTeX can be executed with a
* specific PDF viewer, and the PDF file can be specified.
*
* @param pdfFile - The path of a PDF File compiled from the filePath of args.
* @param pdfUri - The path of a PDF File compiled from the filePath of args.
* If undefined, it is automatically detected.
* @param args - The arguments of forward SyncTeX. If undefined, the document
* and cursor position of activeTextEditor are used.
* @param forcedViewer - Indicates a PDF viewer with which SyncTeX is executed
* ('auto', 'tabOrBrowser', or 'external').
*/
function toPDF(pdfFile?: string, args?: {line: number, filePath: string}, forcedViewer: 'auto' | 'tabOrBrowser' | 'external' = 'auto') {
function toPDF(pdfUri?: vscode.Uri, args?: {line: number, filePath: string}, forcedViewer: 'auto' | 'tabOrBrowser' | 'external' = 'auto') {
let line: number
let filePath: string
let character = 0
Expand Down Expand Up @@ -222,7 +222,7 @@ function toPDF(pdfFile?: string, args?: {line: number, filePath: string}, forced
logger.log('No root file found.')
return
}
const targetPdfFile = pdfFile ?? lw.file.getPdfPath(rootFile)
const targetPdfFile = pdfUri ?? vscode.Uri.file(lw.file.getPdfPath(rootFile))
if (active.document.lineCount === line &&
active.document.lineAt(line - 1).text === '') {
line -= 1
Expand All @@ -234,10 +234,10 @@ function toPDF(pdfFile?: string, args?: {line: number, filePath: string}, forced

callSyncTeXToPDF(line, character, filePath, targetPdfFile, configuration.get('synctex.indicator') as 'none' | 'circle' | 'rectangle').then((record) => {
void lw.viewer.locate(targetPdfFile, record)
}).catch(() => {
}).catch(async () => {
try {
logger.log(`Forward with synctex.js from ${filePath} to ${pdfFile} on line ${line}.`)
const record = syncTeXToPDF(line, filePath, targetPdfFile)
logger.log(`Forward with synctex.js from ${filePath} to ${pdfUri?.toString(true)} on line ${line}.`)
const record = await syncTeXToPDF(line, filePath, targetPdfFile)
if (!record) {
return
}
Expand All @@ -259,21 +259,21 @@ function toPDF(pdfFile?: string, args?: {line: number, filePath: string}, forced
* @param line - The line number in the TeX file.
* @param col - The character position (column) in the line.
* @param filePath - The path of the TeX file.
* @param pdfFile - The path of the PDF file.
* @param pdfUri - The path of the PDF file.
* @param indicator - The type of the SyncTex indicator.
* @returns A promise resolving to a SyncTeXRecordToPDF object or a
* SyncTeXRecordToPDF[] object.
*/
function callSyncTeXToPDF(line: number, col: number, filePath: string, pdfFile: string, indicator: 'none' | 'circle' | 'rectangle'): Promise<SyncTeXRecordToPDF>
function callSyncTeXToPDF(line: number, col: number, filePath: string, pdfFile: string, indicator: 'none' | 'circle' | 'rectangle'): Promise<SyncTeXRecordToPDFAll[]>
function callSyncTeXToPDF(line: number, col: number, filePath: string, pdfFile: string, indicator: 'none' | 'circle' | 'rectangle'): Promise<SyncTeXRecordToPDF> | Promise<SyncTeXRecordToPDFAll[]> {
function callSyncTeXToPDF(line: number, col: number, filePath: string, pdfUri: vscode.Uri, indicator: 'none' | 'circle' | 'rectangle'): Promise<SyncTeXRecordToPDF>
function callSyncTeXToPDF(line: number, col: number, filePath: string, pdfUri: vscode.Uri, indicator: 'none' | 'circle' | 'rectangle'): Promise<SyncTeXRecordToPDFAll[]>
function callSyncTeXToPDF(line: number, col: number, filePath: string, pdfUri: vscode.Uri, indicator: 'none' | 'circle' | 'rectangle'): Promise<SyncTeXRecordToPDF> | Promise<SyncTeXRecordToPDFAll[]> {
const configuration = vscode.workspace.getConfiguration('latex-workshop')
const docker = configuration.get('docker.enabled')

const args = ['view', '-i'].concat([
`${line}${indicator === 'rectangle' ? ':0' : `:${col + 1}`}:${docker ? path.basename(filePath) : filePath}`,
'-o',
docker ? path.basename(pdfFile) : pdfFile
docker ? path.basename(pdfUri.fsPath) : pdfUri.fsPath
])

let command = configuration.get('synctex.path') as string
Expand All @@ -286,8 +286,8 @@ function callSyncTeXToPDF(line: number, col: number, filePath: string, pdfFile:
}
}
const logTag = docker ? 'Docker' : 'SyncTeX'
logger.log(`Forward from ${filePath} to ${pdfFile} on line ${line}.`)
const proc = cs.spawn(command, args, {cwd: path.dirname(pdfFile)})
logger.log(`Forward from ${filePath} to ${pdfUri.toString(true)} on line ${line}.`)
const proc = cs.spawn(command, args, {cwd: path.dirname(pdfUri.fsPath)})
proc.stdout.setEncoding('utf8')
proc.stderr.setEncoding('utf8')

Expand Down Expand Up @@ -418,25 +418,25 @@ function toPDFFromRef(args: {line: number, filePath: string}) {
*
* @param data - ClientRequest data containing the type ('reverse_synctex') and
* position information.
* @param pdfPath - The path of the PDF file.
* @param pdfUri - The path of the PDF file.
*/
async function toTeX(data: Extract<ClientRequest, {type: 'reverse_synctex'}>, pdfPath: string) {
async function toTeX(data: Extract<ClientRequest, {type: 'reverse_synctex'}>, pdfUri: vscode.Uri) {
let record: SyncTeXRecordToTeX

// We only use synctex.js for backward sync as the binary cannot handle CJK encodings #4239.
//
// const configuration = vscode.workspace.getConfiguration('latex-workshop')
// const docker = configuration.get('docker.enabled')
// try {
// record = await callSyncTeXToTeX(data.page, data.pos[0], data.pos[1], pdfPath)
// record = await callSyncTeXToTeX(data.page, data.pos[0], data.pos[1], pdfUri)
// if (docker && process.platform === 'win32') {
// record.input = path.join(path.dirname(pdfPath), record.input.replace('/data/', ''))
// record.input = path.join(path.dirname(pdfUri), record.input.replace('/data/', ''))
// }
// } catch {
// }
try {
logger.log(`Backward from ${pdfPath} at x=${data.pos[0]}, y=${data.pos[1]} on page ${data.page}.`)
const temp = syncTeXToTeX(data.page, data.pos[0], data.pos[1], pdfPath)
logger.log(`Backward from ${pdfUri.toString(true)} at x=${data.pos[0]}, y=${data.pos[1]} on page ${data.page}.`)
const temp = await syncTeXToTeX(data.page, data.pos[0], data.pos[1], pdfUri)
if (!temp) {
return
}
Expand Down Expand Up @@ -675,10 +675,10 @@ function animateToNotify(editor: vscode.TextEditor, position: vscode.Position) {
* viewer. It constructs the command and arguments based on user configuration.
*
* @param line - The line number in the PDF.
* @param pdfFile - The path of the PDF file.
* @param pdfUri - The path of the PDF file.
* @param rootFile - The path of the root TeX file.
*/
function syncTeXExternal(line: number, pdfFile: string, rootFile: string) {
function syncTeXExternal(line: number, pdfUri: vscode.Uri, rootFile: string) {
if (!vscode.window.activeTextEditor) {
return
}
Expand All @@ -693,12 +693,12 @@ function syncTeXExternal(line: number, pdfFile: string, rootFile: string) {
if (args) {
args = args.map(arg => {
return replaceArgumentPlaceholders(rootFile, lw.file.tmpDirPath)(arg)
.replace(/%PDF%/g, pdfFile)
.replace(/%PDF%/g, pdfUri.fsPath)
.replace(/%LINE%/g, line.toString())
.replace(/%TEX%/g, texFile)
})
}
logger.logCommand(`Opening external viewer for SyncTeX from ${pdfFile} .`, command, args)
logger.logCommand(`Opening external viewer for SyncTeX from ${pdfUri.toString(true)} .`, command, args)
const proc = cs.spawn(command, args)
let stdout = ''
proc.stdout.on('data', newStdout => {
Expand Down
40 changes: 21 additions & 19 deletions src/locate/synctex/worker.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as vscode from 'vscode'
import * as fs from 'fs'
import * as iconv from 'iconv-lite'
import * as path from 'path'
Expand Down Expand Up @@ -91,32 +92,33 @@ function toRect(blocks: any): Rectangle {
}
}

function parseSyncTexForPdf(pdfFile: string): PdfSyncObject | undefined {
const filename = path.basename(pdfFile, path.extname(pdfFile))
const dir = path.dirname(pdfFile)
const synctexFile = path.resolve(dir, filename + '.synctex')
const synctexFileGz = synctexFile + '.gz'
async function parseSyncTexForPdf(pdfUri: vscode.Uri): Promise<PdfSyncObject | undefined> {
const filename = path.basename(pdfUri.fsPath, path.extname(pdfUri.fsPath))
const dir = path.dirname(pdfUri.fsPath)
const synctexUri = pdfUri.with({ path: path.resolve(dir, filename + '.synctex') })
const synctexUriGz = synctexUri.with({ path: synctexUri.path + '.gz' })

if (fs.existsSync(synctexFile)) {
if (await lw.file.exists(synctexUri)) {
await vscode.workspace.fs.stat(synctexUri)
try {
logger.log(`Parsing .synctex ${synctexFile} .`)
const s = fs.readFileSync(synctexFile, {encoding: 'binary'})
return parseSyncTex(s)
logger.log(`Parsing .synctex ${synctexUri.toString(true)} .`)
const s = await lw.file.read(synctexUri)
return parseSyncTex(s ?? '')
} catch (e: unknown) {
logger.logError(`Failed parsing .synctex ${synctexFile}:`, e)
logger.logError(`Failed parsing .synctex ${synctexUri.toString(true)}:`, e)
}
} else if (fs.existsSync(synctexFileGz)) {
} else if (await lw.file.exists(synctexUriGz)) {
try {
logger.log(`Parsing .synctex.gz ${synctexFileGz} .`)
const data = fs.readFileSync(synctexFileGz)
logger.log(`Parsing .synctex.gz ${synctexUriGz.toString(true)} .`)
const data = await vscode.workspace.fs.readFile(synctexUriGz)
const b = zlib.gunzipSync(data)
const s = b.toString('binary')
return parseSyncTex(s)
} catch (e: unknown) {
logger.logError(`Failed parsing .synctex.gz ${synctexFileGz}:`, e)
logger.logError(`Failed parsing .synctex.gz ${synctexUriGz.toString(true)}:`, e)
}
}
logger.log(`${synctexFile}, ${synctexFileGz} not found.`)
logger.log(`${synctexUri.toString(true)}, ${synctexUriGz.toString(true)} not found.`)
return undefined
}

Expand All @@ -142,8 +144,8 @@ function findInputFilePathForward(filePath: string, pdfSyncObject: PdfSyncObject
return
}

function syncTeXToPDF(line: number, filePath: string, pdfFile: string): SyncTeXRecordToPDF | undefined {
const pdfSyncObject = parseSyncTexForPdf(pdfFile)
async function syncTeXToPDF(line: number, filePath: string, pdfUri: vscode.Uri): Promise<SyncTeXRecordToPDF | undefined> {
const pdfSyncObject = await parseSyncTexForPdf(pdfUri)
if (!pdfSyncObject) {
return undefined
}
Expand Down Expand Up @@ -177,8 +179,8 @@ function syncTeXToPDF(line: number, filePath: string, pdfFile: string): SyncTeXR
return { page: blocks1[0].page, x: c1.left + pdfSyncObject.offset.x, y: bottom + pdfSyncObject.offset.y, indicator: true }
}

function syncTeXToTeX(page: number, x: number, y: number, pdfPath: string): SyncTeXRecordToTeX | undefined {
const pdfSyncObject = parseSyncTexForPdf(pdfPath)
async function syncTeXToTeX(page: number, x: number, y: number, pdfUri: vscode.Uri): Promise<SyncTeXRecordToTeX | undefined> {
const pdfSyncObject = await parseSyncTexForPdf(pdfUri)
if (!pdfSyncObject) {
return undefined
}
Expand Down
Loading

0 comments on commit 1f3b9c5

Please sign in to comment.