Заранее предупреждаю - всё тут немного сумбурно...
Графический редактор Inkscape (если пользователю и Inkscape повезёт с установкой) может запускать Python-скрипты рисующие всякие линии, круги, прямоугольники и даже текст.
Текст плагина для поиска совпадений в двух текстовых файлах (textfa.txt и textfb.txt):
#!/usr/bin/env python
# coding=utf-8
# импортируем графическую магию и прочую требуху
import inkex
from inkex import TextElement, Group, Layer, Tspan, PathElement
FntSz = 3.175 # будем выводить текст - так вот это размер текста
FntHt = 1.6 # расстояние между строками
FilenameA = '/home/user_name/textfa.txt' # файл первый
FilenameB = '/home/user_name/textfb.txt' # файл второй
sxA = 0 # координаты для вывода текста из первого файла
syA = 0
sxB = 1000 # координаты для вывода текста из второго файла
syB = 0
class Comparator(inkex.EffectExtension): # ну что сказать...
#--#--#-----------I want to distincs the exact "SourceText" in this group somehow -------------------------------
def effect(self): # этот метод класса Comparator запускается из Инкскейпа
ar23A = ['nothing','here'] # подготавливаем массив для чтения из первого файла
ar23B = ['nothing','here'] # подготавливаем массив для чтения из второго файла
Layer = self.PrepareThelayer('Habr23') # приготавливаем пустой Графич_слой для рисования
with open(FilenameA, 'r') as file:
BigTxA = file.read() # читаем текст из первого файла
ar23A = BigTxA.split('\n') # разбиваем текст в массив на строки
self.drawText(Layer, sxA, syA, ar23A) # выводим массив строк в Графич_файл
with open(FilenameB, 'r') as file:
BigTxB = file.read() # читаем текст из второго файла
ar23B = BigTxB.split('\n') # разбиваем текст в массив на строки
self.drawText(Layer, sxB, syB, ar23B) # выводим массив строк в Графич_файл
for nA in range(0, len(ar23A)): # перебираем оба массива со строками в поисках...
for nB in range(0, len(ar23B)):
if (ar23A[nA] == ar23B[nB]): # ...в поисках одинаковых строк
if(len(ar23A[nA]) > 1): # избегаем пустых строк
yA = nA * FntHt * FntSz # подготавливаем координаты для линии между совпадающими строками
yB = nB * FntHt * FntSz
self.drawLine(Layer, sxA+200,syA+yA, sxB, syB+yB) # рисуем линию между совпадающими строками
#--#--#---------------------------------------------------------------
def drawText(self, Layer, x, y, Tmass):
# начинаем церемонию создания текст_блока
elem = TextElement(x=str(x), y=str(y))
elem.style = { # задаём внешний вид нашего текст_блока
'font-size':str(FntSz), # размер шрифта
'line-height':str(FntHt), # расстояние между строк
'font-family':'courier', # и т.д.
'-inkscape-font-specification':'courier',
'stroke-width':'0.264583'}
# ещё немного церемониальных заклинаний
elem.set('xml:space',"preserve")
# и начинаем построчно выводить текст
for n in range(0, len(Tmass)):
tx23 = Tspan(Tmass[n]) # создаем строку
tx23.set('sodipodi:role',"line") # магия...
tx23.set('x' ,x)
tx23.set('y' , y + (n * FntHt * FntSz))
elem.add(tx23) # присоединяя каждую строку к текстовому блоку
# выводим текстовый блок в Графич_слой (то есть выводим на экран)
Layer.add(elem) # выводим созданный текстовый блок на экран
#--#--#---------------------------------------------------------------
def PrepareThelayer(self, Lname):
# сперва попробуем найти Графич_слой с желаемым имменем
svg = self.document.getroot() # ищем в документе
for g in svg.xpath('//svg:g', namespaces=inkex.NSS):
if g.get(inkex.addNS('groupmode', 'inkscape')) == 'layer':
t23 = g.get(inkex.addNS('label', 'inkscape'))
if (t23 == Lname): # совпадает ли имя Графич_слоя?
for child in g: # если это желаемый слой
g.remove(child) # очищаем его содержимое
return g
# Графич_слой с желаемым именем мы не нашли
# поэтому создаём новый Графич_слой с желаемым именем
newlayer=self.svg.add(Layer.new(Lname))
return newlayer
#--#--#---------------------------------------------------------------
def drawLine(self, layer, x0,y0, x99, y99):
# рисуем линию соблюдая все церемонии Инкскейпа
# сперва создаем линию...
line = PathElement()
line.set('fill','none')
line.set('stroke',"#4FF") # цвет
line.set('stroke-width','0.8') # толщину
line.set('d','M %f %f %f %f' % (x0, y0, x99, y99)) # координаты
# теперь выводим линию в Графич_слой (то есть выводим на экран)
layer.append(line)
# Питонская ООП-магия
if __name__ == '__main__':
Comparator().run()
Теперь будут некоторые пояснения. Пользователь редактора Inkscape может запускать Python-скрипты через меню.

В верхнем меню графического редактора Inkscape помимо всяческих File, Edit, View – есть волшебное подменю Extensions (Расширения) при нажатии на которое выводится список уже имеющихся в редакторе и готовых к запуску Python-скриптов.
...Создатели Inkscape предписывают Linux-поклоннику держать его самодельные Python-скрипты в районе “домашней” папки “/home/user_name/.config/inkscape/extensions/” (для Windows-пользователей там что-то своё).
В этой же папке следует расположить файл с расширением *.inx
В моём случае это был файл "proba01.inx"
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<_name>proba-1</_name>
<id>something12345</id>
<dependency type="executable" location="extensions">proba01.py</dependency>
<effect>
<object-type>all</object-type>
</effect>
<script>
<command reldir="extensions" interpreter="python">proba01.py</command>
</script>
</inkscape-extension>
Я разместил в папке “/home/user_name/.config/inkscape/extensions/” два вышеупомянутых файла "proba01.py" и "proba01.inx", перезапустил Inkscape и с радостью обнаружил в подменю “Extensions” пункт “proba-1” который запускал скрипт “proba01.py”

И вот результат работы скрипта:

Выгдядит достаточно наукообразно.
Я планирую улучшить этот скрипт. С радостью выслушаю мнения.
(где .. тут кнопка "Сохранить" ?)