Commit 76dabe2e authored by Florian Münchbach's avatar Florian Münchbach Committed by Philipp Hörist

[syntax_highlight] Port Syntax Highlighting Plugin

parent 54546918
This diff is collapsed.
# Syntax Highlighting Plugin for Gajim
[Gajim]( Plugin that highlights source code blocks in chatbox.
## Installation
The recommended way of installing this plugin is to use
Gajim's Plugin Installer.
For more information and instruction on how to install plugins manually, please
refer to the [Gajim Plugin Wiki seite](
## Usage
This plugin uses markdown-style syntax to identify which parts of a message
should be formatted as code in the chatbox.
Inline source code will be highlighted when placed in between `two single
The language used to highlight the syntax of inline code is selected as the
default language in the plugin settings.
Multi-line code blocks are started by three back-ticks followed by a newline.
Optionally, a language can be specified directly after the opening back-ticks and
before the line break:
Note, that the last line of a code block may only contain the closing back-ticks,
i.e. there must be a newline here.
In case no languge is specified with the opening tag or the specified language
could not be identified, the default languge configured in the settings is
You can test it by copying and sending the following text to one of your
def test():
print("Hello, world!")
(**Note:** your contact will not receive highlighted text unless she is also
using the plugin.)
## Configuration
The configuration can be found via 'Gajim' > 'Plugins', then select the
'Source Code Syntax Highlight' Plugin and click the gears symbol.
The configuration options let you specify many details how code is formatted,
including default language, style, font settings, background color and formatting
of the code markers.
In the configuration window, the current settings are displayed in an
interactive preview pannel. This allows you to directly check how code would
look like in the message
## Report Bugs and Feature Requests
For bug reports, please report them to the [Gajim Plugin Issue tracker]([FlorianMuenchbach]=&issue[description]=Gajim%20Version%3A%20%0APlugin%20Version%3A%0AOperating%20System%3A&issue[title]=[syntax_highlight]).
Please make sure that the issue you create contains `[syntax_highlight]` in the
title and information such as Gajim version, Plugin version, Operating system,
## Debug
The plugin adds its own logger. It can be used to set a specific debug level
for this plugin and/or filter log messages.
gajim --loglevel gajim.plugin_system.syntax_highlight=DEBUG
in a terminal to display the debug messages.
## Known Issues / ToDo
* ~~Gajim crashes when correcting a message containing highlighted code.~~
(fixed in version 1.1.0)
## Credits
Since I had no experience in writing Plugins for Gajim, I used the
[Latex Plugin](
written by Yves Fischer and Yann Leboulanger as an example and copied a big
portion of initial code. Therefore, credits go to the authors of the Latex
Plugin for providing an example.
The syntax highlighting itself is done by [pygments](
from .syntax_highlight import SyntaxHighlighterPlugin
This diff is collapsed.
import logging
from gi.repository import Gtk as gtk
from gi.repository import Pango
from pygments.formatter import Formatter
from gajim.plugins.helpers import log
log = logging.getLogger('gajim.plugin_system.syntax_highlight')
class GTKFormatter(Formatter):
name = 'GTK Formatter'
aliases = ['textbuffer', 'gtk']
filenames = []
def __init__(self, **options):
super(GTKFormatter, self).__init__(**options)
#Formatter.__init__(self, **options)
self.tags = {}
self.mark = options.get('start_mark', None)
def create_tag_for_token(ttype, highlighting_style):
style = highlighting_style.style_for_token(ttype)
tag =
if 'bgcolor' in style and not style['bgcolor'] is None:
tag.set_property('background', '#%s' % style['bgcolor'])
if 'bold' in style and style['bold']:
tag.set_property('weight', Pango.Weight.BOLD)
if 'border' in style and not style['border'] is None:
if 'color' in style and not style['color'] is None:
tag.set_property('foreground', '#%s' % style['color'])
if 'italic' in style and style['italic']:
tag.set_property('style', Pango.Style.ITALIC)
if 'mono' in style and not style['mono'] is None:
tag.set_property('family', 'Monospace')
tag.set_property('family-set', True)
if 'roman' in style and not style['roman'] is None:
if 'sans' in style and not style['sans'] is None:
tag.set_property('family', 'Sans')
tag.set_property('family-set', True)
if 'underline' in style and style['underline']:
tag.set_property('underline', 'single')
return tag
def get_tag(self, ttype, buf):
Creates, stores and returs a tag for a given token type.
This method ensures that a tag style is created only once.
Furthermore, the tag will be added to the given Gtk.TextBuffer's tag table.
tag = None
if ttype in self.tags:
tag = self.tags[ttype]
tag = GTKFormatter.create_tag_for_token(ttype,
self.tags[ttype] = tag
return tag
def set_insert_pos_mark(self, mark):
self.mark = mark
def format(self, tokensource, outfile):
if not isinstance(outfile, gtk.TextBuffer) or outfile is None:
log.warn("Did not get a buffer to format...")
buf = outfile
end_iter = buf.get_end_iter()
start_mark = self.mark
start_iter = buf.get_iter_at_mark(start_mark) if not start_mark is None \
else end_iter
last_ttype = None
last_start = start_iter
last_end = buf.get_end_iter()
last_fixed_start = last_start
reset = True
for ttype, value in tokensource:
search = None
if last_ttype is not None and ttype != last_ttype:
tag = self.get_tag(last_ttype, buf)
buf.apply_tag(tag, last_fixed_start, last_end)
search = last_end.forward_search(value, gtk.TextSearchFlags.TEXT_ONLY, end_iter)
reset = True
# in case last_ttype is None, i.e. first loop walkthrough:
# last_start to end_iter is the full code block.
search = last_start.forward_search(value, gtk.TextSearchFlags.TEXT_ONLY, end_iter)
# Prepare for next iteration
last_ttype = ttype
if search is not None:
(last_start, last_end) = search
# If we've found the end of a sequence of similar type tokens or if
# we are in the first loop iteration, set the fixed point
if reset:
last_fixed_start = last_start
reset = False
# Hm... Nothing found, but tags left? Seams there's nothing we
# can do now.
# Don't forget to point to the correct file when switching to another
# branch or so...
name: Source Code Syntax Highlight
short_name: syntax_highlight
version: 1.1.0
description: Source Code Syntax Highlighting in the chatbox.
It uses markdown-style syntax, i.e. text in between `single backticks` is
rendered as inline code, ```language
selection is possible in multi-line code snippets in between triple-backticks
Note the newlines in this case...
*Note:* You need to have pygments installed.
Please refer to the plugin's Wiki page for more information.
Changing settings will take effect after closing and opening the message
tab/window again.
authors = Florian Muenchbach
homepage =
min_gajim_version: 1.1.0
max_gajim_version: 1.1.90
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment