Browse Source

added styntax highlighting, ooooyeah!

Bachir Soussi Chiadmi 7 years ago
parent
commit
8e8a55fc19
3 changed files with 146 additions and 3 deletions
  1. 4 0
      classes/content.py
  2. 10 3
      classes/design.py
  3. 132 0
      classes/highlighter.py

+ 4 - 0
classes/content.py

@@ -8,6 +8,8 @@ from PyQt5.QtCore import QSettings
 from PyQt5.QtGui import QKeySequence
 from PyQt5.QtGui import QKeySequence
 from PyQt5.QtWidgets import QWidget, QLabel, QHBoxLayout, QVBoxLayout, QSplitter, QListWidget, QListWidgetItem, QAbstractItemView, QPushButton, QInputDialog, QPlainTextEdit, QTextEdit, QShortcut
 from PyQt5.QtWidgets import QWidget, QLabel, QHBoxLayout, QVBoxLayout, QSplitter, QListWidget, QListWidgetItem, QAbstractItemView, QPushButton, QInputDialog, QPlainTextEdit, QTextEdit, QShortcut
 
 
+from classes import highlighter
+
 import markdown2
 import markdown2
 import json
 import json
 
 
@@ -193,6 +195,8 @@ class MarkdownEditor(QWidget):
 
 
       self.editor = QPlainTextEdit(self)
       self.editor = QPlainTextEdit(self)
       self.editor.setStyleSheet(self.styles)
       self.editor.setStyleSheet(self.styles)
+
+      self.hl=highlighter.Highlighter(self.editor.document(),"md")
       self.hbox.addWidget(self.editor)
       self.hbox.addWidget(self.editor)
 
 
       self.viewer = QTextEdit(self)
       self.viewer = QTextEdit(self)

+ 10 - 3
classes/design.py

@@ -11,6 +11,11 @@ from PyQt5.QtWebKit import QWebSettings
 from PyQt5.QtWebKitWidgets import QWebView, QWebInspector
 from PyQt5.QtWebKitWidgets import QWebView, QWebInspector
 from PyQt5.QtPrintSupport import QPrintPreviewDialog, QPrinter
 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):
 class WebkitView(QWebView):
    def __init__(self, parent, core):
    def __init__(self, parent, core):
@@ -170,12 +175,14 @@ class WebViewToolBar(QWidget):
 
 
 
 
 class CodeEditor(QPlainTextEdit):
 class CodeEditor(QPlainTextEdit):
-   def __init__(self, core, tabs, file=None):
+   def __init__(self, core, tabs, file, mode):
       super(CodeEditor, self).__init__()
       super(CodeEditor, self).__init__()
       self.core = core
       self.core = core
       self.tabs = tabs
       self.tabs = tabs
       self.file = file
       self.file = file
       self.setText()
       self.setText()
+      self.setTabStopWidth(15)
+      self.hl= highlighter.Highlighter(self.document(),mode)
 
 
       self.shortcut = QShortcut(QKeySequence("Ctrl+s"), self)
       self.shortcut = QShortcut(QKeySequence("Ctrl+s"), self)
       self.shortcut.activated.connect(self.save)
       self.shortcut.activated.connect(self.save)
@@ -233,8 +240,8 @@ class Editor(QWidget):
       # Initialize tab screen
       # Initialize tab screen
       self.tabs = QTabWidget()
       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
       # Add tabs
       self.tabs.addTab(self.scsstab,"scss")
       self.tabs.addTab(self.scsstab,"scss")

+ 132 - 0
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 <kib2@free.fr>
+#
+# 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_())