diff --git a/classes/content.py b/classes/content.py index bfe596f..491bb42 100644 --- a/classes/content.py +++ b/classes/content.py @@ -8,6 +8,8 @@ from PyQt5.QtCore import QSettings from PyQt5.QtGui import QKeySequence from PyQt5.QtWidgets import QWidget, QLabel, QHBoxLayout, QVBoxLayout, QSplitter, QListWidget, QListWidgetItem, QAbstractItemView, QPushButton, QInputDialog, QPlainTextEdit, QTextEdit, QShortcut +from classes import highlighter + import markdown2 import json @@ -193,6 +195,8 @@ class MarkdownEditor(QWidget): self.editor = QPlainTextEdit(self) self.editor.setStyleSheet(self.styles) + + self.hl=highlighter.Highlighter(self.editor.document(),"md") self.hbox.addWidget(self.editor) self.viewer = QTextEdit(self) diff --git a/classes/design.py b/classes/design.py index 200906f..cc9d185 100644 --- a/classes/design.py +++ b/classes/design.py @@ -11,6 +11,11 @@ from PyQt5.QtWebKit import QWebSettings from PyQt5.QtWebKitWidgets import QWebView, QWebInspector from PyQt5.QtPrintSupport import QPrintPreviewDialog, QPrinter +# from pygments import highlight +# from pygments.lexers import * +# from pygments.formatter import Formatter +from classes import highlighter + class WebkitView(QWebView): def __init__(self, parent, core): @@ -170,12 +175,14 @@ class WebViewToolBar(QWidget): class CodeEditor(QPlainTextEdit): - def __init__(self, core, tabs, file=None): + def __init__(self, core, tabs, file, mode): super(CodeEditor, self).__init__() self.core = core self.tabs = tabs self.file = file self.setText() + self.setTabStopWidth(15) + self.hl= highlighter.Highlighter(self.document(),mode) self.shortcut = QShortcut(QKeySequence("Ctrl+s"), self) self.shortcut.activated.connect(self.save) @@ -233,8 +240,8 @@ class Editor(QWidget): # Initialize tab screen self.tabs = QTabWidget() - self.scsstab = CodeEditor(core, self.tabs, 'assets/css/styles.scss') - self.jstab = CodeEditor(core, self.tabs, 'assets/js/script.js') + self.scsstab = CodeEditor(core, self.tabs, 'assets/css/styles.scss', "scss") + self.jstab = CodeEditor(core, self.tabs, 'assets/js/script.js', 'js') # Add tabs self.tabs.addTab(self.scsstab,"scss") diff --git a/classes/highlighter.py b/classes/highlighter.py new file mode 100644 index 0000000..f25fbcc --- /dev/null +++ b/classes/highlighter.py @@ -0,0 +1,132 @@ +# -*- coding: utf-8 -*- +import sys +import re +from PyQt5 import QtCore, QtGui +from pygments import highlight +from pygments.lexers import * +from pygments.formatter import Formatter +from pygments.styles import get_all_styles, get_style_by_name +import time + +# Copyright (C) 2008 Christophe Kibleur +# +# This file is part of WikiParser (http://thewikiblog.appspot.com/). +# + +def hex2QColor(c): + r=int(c[0:2],16) + g=int(c[2:4],16) + b=int(c[4:6],16) + return QtGui.QColor(r,g,b) + + +class QFormatter(Formatter): + def __init__(self, linenos=True, style="default"): #, style + Formatter.__init__(self) + self.data=[] + self.style = get_style_by_name(style) + self.linenos = linenos + # styles = list(get_all_styles()) + # print(styles) + # Create a dictionary of text styles, indexed + # by pygments token names, containing QTextCharFormat + # instances according to pygments' description + # of each style + + self.styles={} + for token, style in self.style: + qtf=QtGui.QTextCharFormat() + + if style['color']: + qtf.setForeground(hex2QColor(style['color'])) + if style['bgcolor']: + qtf.setBackground(hex2QColor(style['bgcolor'])) + if style['bold']: + qtf.setFontWeight(QtGui.QFont.Bold) + if style['italic']: + qtf.setFontItalic(True) + if style['underline']: + qtf.setFontUnderline(True) + + self.styles[str(token)]=qtf + + def format(self, tokensource, outfile): + global styles + # We ignore outfile, keep output in a buffer + self.data=[] + + # Just store a list of styles, one for each character + # in the input. Obviously a smarter thing with + # offsets and lengths is a good idea! + print(tokensource) + + for ttype, value in tokensource: + l=len(value) + t=str(ttype) + self.data.extend([self.styles[t],]*l) + + +class Highlighter(QtGui.QSyntaxHighlighter): + + def __init__(self, parent, mode): + QtGui.QSyntaxHighlighter.__init__(self, parent) + self.tstamp=time.time() + + # Keep the formatter and lexer, initializing them + # may be costly. + if not mode == "md": + self.formatter=QFormatter(linenos=True, style="monokai-hcb") + else: + self.formatter=QFormatter(linenos=False, style="github") + + self.lexer=get_lexer_by_name(mode) + + def highlightBlock(self, text): + """Takes a block, applies format to the document. + according to what's in it. + """ + + # I need to know where in the document we are, + # because our formatting info is global to + # the document + cb = self.currentBlock() + p = cb.position() + + # The \n is not really needed, but sometimes + # you are in an empty last block, so your position is + # **after** the end of the document. + text=str(self.document().toPlainText())+'\n' + + # Yes, re-highlight the whole document. + # There **must** be some optimizacion possibilities + # but it seems fast enough. + highlight(text,self.lexer,self.formatter) + + # Just apply the formatting to this block. + # For titles, it may be necessary to backtrack + # and format a couple of blocks **earlier**. + for i in range(len(str(text))): + try: + self.setFormat(i,1,self.formatter.data[p+i]) + except IndexError: + pass + + # I may need to do something about this being called + # too quickly. + self.tstamp=time.time() + + +# if __name__ == "__main__": +# app = QtGui.QApplication(sys.argv) +# +# rst = QtGui.QPlainTextEdit() +# rst.setWindowTitle('reSt') +# hl=Highlighter(rst.document(),"rest") +# rst.show() +# +# python = QtGui.QPlainTextEdit() +# python.setWindowTitle('python') +# hl=Highlighter(python.document(),"python") +# python.show() +# +# sys.exit(app.exec_())