1

I have a program to write a text and when I click on the 'compile' button, it compiles to latex, converts to pdf and displays it on my application. The problem is that when I have a compilation error, the application bugs and that's it. I'd like to know if it's possible to recover compilation errors without the application crashing. I tried with try/expect but it's not a python error so it doesn't work.

You will need PDF.js to view the pdf https://mozilla.github.io/pdf.js/getting_started/#download

Ui :


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(841, 481)
        self.horizontalLayout = QtWidgets.QHBoxLayout(Dialog)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.gridLayout = QtWidgets.QGridLayout()
        self.gridLayout.setObjectName("gridLayout")
        self.textEdit = QtWidgets.QTextEdit(Dialog)
        self.textEdit.setMinimumSize(QtCore.QSize(0, 200))
        self.textEdit.setObjectName("textEdit")
        self.gridLayout.addWidget(self.textEdit, 0, 0, 1, 1)
        self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
        self.buttonBox.setOrientation(QtCore.Qt.Vertical)
        self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
        self.buttonBox.setObjectName("buttonBox")
        self.gridLayout.addWidget(self.buttonBox, 0, 1, 1, 1)
        #self.textEdit_2 = QtWidgets.QTextEdit(Dialog)
        #self.textEdit_2.setObjectName("textEdit_2")
        #self.gridLayout.addWidget(self.textEdit_2, 1, 0, 1, 1)
        self.horizontalLayout.addLayout(self.gridLayout)

        self.retranslateUi(Dialog)
        self.buttonBox.accepted.connect(Dialog.accept)
        self.buttonBox.rejected.connect(Dialog.reject)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))

app:

import os
import sys
from PyQt5.QtWidgets import QDialog, QPushButton, QWidget, QApplication
from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets
from sympy import Symbol
import untitled

x=Symbol('x')
class Test(QDialog, untitled.Ui_Dialog):
    def __init__(self):
        super(Test, self).__init__()
        self.setupUi(self)

        self.bouton= QPushButton('compile',self)
        self.horizontalLayout.addWidget(self.bouton)
        self.bouton.clicked.connect(self.crertest)

        self.widget = QWidget(self)
        self.gridLayout.addWidget(self.widget, 1, 0, 1, 1)
        self.t = Window()
        lay = QtWidgets.QVBoxLayout(self.widget)
        lay.addWidget(self.t)

    def crertest(self):
        try :
            def preambule(*packages):
                p = ""
                for i in packages:
                    p = p + "\\usepackage{" + i + "}\n"
                return p
            start = "\\documentclass[12pt,a4paper,french]{article}\n\\usepackage[utf8]{inputenc}\n"
            start = start + preambule('amsmath','graphicx')
            start = start + "\\begin{document}\n"
            end = "\\end{document}"
            body = self.textEdit.toPlainText()

            container = start + body + end
            file = "mypdf.tex"
            if os.path.exists(file):
                os.remove(file)
            fichier = open("mypdf.tex", "x")  #
            fichier.write(container)
            fichier.close()

            instructions = "pdflatex " + file
            os.system(instructions)
            readpdf = "START " + file[:-4] + ".pdf"
            self.t.loadd()
        except:
            print('Fail')

PDFJS = 'file:///C:/Users/pdf_js/web/viewer.html' #Path too viewer.htlm in your pddf_js folder
PDF = 'file:///C:/Users/mypdf.pdf' #Path to your pdf


class Window(QtWebEngineWidgets.QWebEngineView):
    def __init__(self):
        super(Window, self).__init__()
        self.loadd()
    try:
        def loadd(self):
            self.load(QtCore.QUrl.fromUserInput('%s?file=%s' % (PDFJS, PDF)))
    except:
        print ('Fail 2')
if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = Test()
    main.show()
    app.exec_()

I use the code taken from this post for the pdf display : https://stackoverflow.com/questions/23389001/how-to-render-pdf-using-pdf-js-viewer-in-pyqt

instructions = "pdflatex " + file 

this line compile, but i can't catch error

Colat
  • 33
  • 2
    It looks like the program is a wrapper around os.system("pdflatex "+file). That means that you should be able to run pdflatex file from the command line and see what happens. Also file.log will have the result either way. Are those enlightening? – Teepeemm Mar 03 '20 at 17:38
  • I didn't quite get that or it doesn't really help me. I know mistakes like: ` ! Missing $ inserted. ` What I'd like is to be able to pick up mistakes and do something with them without my application closing down. I hope that's clear ^^ For example, if I have the top error, I display a dialog to say that there is a compilation error and that the text needs to be reviewed. – Colat Mar 03 '20 at 18:10
  • your question is off topic really I think as it is just about python not really about tex (you could ask the same about any non-python program called from python. in the os.system you can presumably call something like pdflatex --interaction=batchmode file || echo hmmm pdflatex had an error then the combination will never return a non zero error code: either pdflatex will succeed or the echo will succeed. – David Carlisle Mar 03 '20 at 20:34
  • The design of TeX itself permits interactive changes to the input unless it's run in "quiet" or uninterruptable mode. The latter is what GUIs (almost?) always specify. Interactive mode often makes it possible to get through a job with an acceptable output when appropriate changes are made in response to an error stoping the run. (It's still necessary to fix the source file.) But this is generally contrary to the "LaTeX way". A loss, in my opinion. – barbara beeton Jul 20 '21 at 23:37

1 Answers1

0

Ok, the question is probably off-topic, and my remarks simply would be harder to digest as a comment. So, please kindly consider my answer.

I'd like to know if it's possible to recover compilation errors without the application crashing.

The common approach newer languages offer is using the try-catch mechanism, i.e throwing an exception, where you try to repair or handle wrongdoings. For a basic start in Phyton see e.g. here: https://www.w3schools.com/python/python_try_except.asp .

When you say it's not a Phyton error, then it will certainly display error messages on the command line. So what should work is to include submission of compile-commands to a shell (i.e. submitting a system call, to DOS, bash whatever), to read back AND to subject those results to a try-catch mechanism.

when I click on the 'compile' button, it compiles to latex, converts to pdf and displays it on my application. The problem is that when I have a compilation error, the application bugs and that's it.

This is usually the finger-print or pattern that you get when doing straight forward programming. Slowing down will bring back pace ... when you apply the test-driven-design paradigm. I.e. for any function you may ever want to use you have tested it prior to its implementation ;-)

Practically you do it by unit testing. See e.g. here: https://docs.python.org/3/library/unittest.html . Your reward will be e.g. beauti-code, shifting focus from code to tests themselves, re-use-ability etc.

Testing (G)UIs can be painful. The better you can split BY CONCEPT between representation(GUI, UI to handle input and output) and function (what it really does), the better you will be on-track.

MS-SPO
  • 11,519