Wednesday, February 12, 2014

Write a Markdown editor with live preview in 50 lines of Python

Hello, I'm the author of Gugodoc (http://gugodoc.free.fr/).

I just wanna share with you a test I did few days ago.

There are a lot of Markdown editors on the market (and some of them are expensive).

Why not try to do one by yourself ?

This experiment will show you that it's pretty easy to do.

 

Introduction


Python is often the weapon of choice when you want to build a little
crossplatform tool. Here I will use 2 well known Python librairies :

 - Pyside for the GUI (Pyside is the official QT wrapper)

 - Markdown2 for markdown conversion

Of, course, you will not get a "professional" editor at the end of this article
but I hope this will be a good enough proof of concept to start your own.

Last, the source code on GitHub for an easier access :

https://github.com/MeyerDumont/markdown-editor

Let's go !

 

1. Download Pyside


This is generally a two step process

 - install qt librairies

 - install the python wrapper

Please follow the exact instructions for your system here :

http://qt-project.org/wiki/Get-PySide

 

2. Download Markdown2


To install it in your Python installation run one of the following:

- pip install markdown2
- pypm install markdown2 # if you use ActivePython
- easy_install markdown2 # if this is the best you have
- python setup.py install

For more information, please go here :

https://github.com/trentm/python-markdown2

 

4. Let's code (Code Explanation) 


We want to have 2 panels, a text editor on the left and a web browser on the right. In QT terms, we need a QSplitter with a  QTextEdit on the left and a QWebView on the right :

        self.editor = QTextEdit(self) 
        self.web = QWebView() 

        splitter = QSplitter(Qt.Horizontal)
        splitter.addWidget(self.editor)
        splitter.addWidget(self.web)

We also need to be notified when the text editor content changes. This is easy with the textChanged signal (=callback) our onTextChanged method will be called :

self.editor.textChanged.connect(self.onTextChanged)
The last thing to do is to get the content of the text editor, convert it to html

        try:
            html = markdown2.markdown(self.my_editor.toPlainText())
        except:
            html = 'Error decoding '

and send the result to the browser :
    self.web.setHtml(html)


That's all folks , here is the entire source code and a video to show you the result



import sys
from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtWebKit import *
from PySide.QtNetwork import *
import markdown2

class MarkdownEditor(QWidget):

    def __init__(self):
        super(MarkdownEditor, self).__init__()       
        self.initUI()

    def initUI(self):     
        hbox = QHBoxLayout(self)

        self.editor = QTextEdit(self)
        self.editor.setFrameShape(QFrame.StyledPanel)
        self.editor.textChanged.connect(self.onTextChanged)

        self.web = QWebView()
        self.web.setHtml("start typing on the left pane")

        splitter = QSplitter(Qt.Horizontal)
        splitter.addWidget(self.editor)
        splitter.addWidget(self.web)

        hbox.addWidget(splitter)
        self.setLayout(hbox)

        QApplication.setStyle(QStyleFactory.create('Cleanlooks'))

        self.setGeometry(300, 300, 800, 400)
        self.setWindowTitle('MarkdownEditor')
        self.show()

    def onTextChanged(self):       
        try:
            html = markdown2.markdown(self.editor.toPlainText())
        except:
            html = 'Error decoding '
        self.web.setHtml(html)

def main():   
    app = QApplication(sys.argv)
    ex = MarkdownEditor()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()


I hope it helps
Meyer

No comments :

Post a Comment