Pull to refresh

Meld в Windows

Reading time 6 min
Views 13K
Краткая справка: Meld — утилита для визуального сравнения файлов/папок.

Наверняка не каждый согласится, что этот иструмент стоит тех танцев с бубном, которые необходимо совершить вокруг него для более менее комфортной работы (Meld слегка не расчитан на работу в Windows, но так как написан на python с использованием GTK, может функционировать и в ней). Я же, потыкав палочкой в бесплатные альтернативы, решил для себя, что если оно заведется, то усилия не будут напрасными.

Предлагаю заинтересовавщимся перейти к делу.

Весть процесс можно разделить на две части: установка и допиливание.

Установка


Основные манипуляции описаны здесь: Meld/Windows. Ниже привожу этот же список со своими комментариями.
  1. Python:
  2. GTK+ All-in-one bundle:
  3. Python gnome bindings:
  4. libglade:
  5. gtksourceview:
  6. Cygwin:
    • Зачем Cygwin я так и не понял. Работает и без него.
    • http://www.cygwin.com/setup.exe.
    • Устанавливаем по ситуации (напр. c:\dev\cygwin).
    • Если же не работает, ни без Cygwin'а, ни с ним, нужно доустановить пакет patch.
  7. Download meld source code:
  8. Add this to your Path:
    • Да да, в переменную PATH нужно добавить пути к python'у (пункт 1, c:\dev\python), к библиотекам (пункты 2, 4 и 5, c:\dev\gtk\bin, c:\dev\glade\bin и c:\dev\gtksourceview\bin) и к Cygwin'у, если установлен (пункт 6, c:\dev\cygwin\bin). Еще можно добавить путь к самому Meld'у (пункт 7, c:\dev\meld\meld-1.3.1)
Теперь, если запустить python, указав путь к Meld'у (c:\dev\meld\meld-1.3.1\meld) в качестве параметра, должно открыться окно Meld'а. Иначе, либо я опечатался, либо вы что-то сделали не так.

Допиливание

  1. Первый вопрос, после успешного запуска: «на кой черт мне это черное консольное окошко?!».

    Решается просто: нужно запускать не python, а pythonw.

  2. Следующий момент: окно утилиты не сохраняет свою позицию и состояние развернутости на весь экран (не то, что fullscreen, а то, что maximized). Возможно, это проблема GTK, возможно, менеджера окон Windows.
    Полностью исправить такое поведение мне не удалось.

    Сохранение позиции окна можно реализовать, сохраняя координаты вручную, но т.к. позиционировать окно до его отображения нельзя, а двигать его уже после отображения некрасиво, я этого делать не стал.

    Решил ограничится сохранением флага WINDOW_STATE_MAXIMIZED. Достигается это путем добавления опции window_maximized в настройки приложения, и обработчика сигнала window-state-event. Сперва, нужно описать обработчик: в файл meldapp.glade (c:\dev\meld\meld-1.3.1\glade2\meldapp.glade) в секцию <widget class="GtkWindow" id="meldapp"> добавить строку <signal name="window_state_event" handler="on_window_state_event"/>:
    --- c:\dev\meld-base\meld-1.3.1\glade2\meldapp.glade
    +++ c:\dev\meld\meld-1.3.1\glade2\meldapp.glade
    @@ -7,6 +7,7 @@
         <property name="title" translatable="yes">Meld</property>
         <property name="icon">pixmaps/icon.png</property>
         <signal name="size_allocate" handler="on_size_allocate"/>
    +    <signal name="window_state_event" handler="on_window_state_event"/>
         <signal name="delete_event" handler="on_delete_event"/>
             <child>
               <widget class="GtkVBox" id="appvbox">
    

    Затем, добавить обработчик: в файл meldapp.py (c:\dev\meld\meld-1.3.1\meldapp.py) добавить метод on_window_state_event:
    --- c:\dev\meld-base\meld-1.3.1\meldapp.py
    +++ c:\dev\meld\meld-1.3.1\meldapp.py
    @@ -615,6 +615,9 @@
             self.prefs.window_size_x = rect.width
             self.prefs.window_size_y = rect.height
    
    +    def on_window_state_event(self, window, state):
    +        self.prefs.window_maximized = bool(state.new_window_state & gtk.gdk.WINDOW_STATE_MAXIMIZED)
    +
         #
         # Toolbar and menu items (file)
         #
    

    Добавить настройку по-умолчанию:
    --- c:\dev\meld-base\meld-1.3.1\meldapp.py
    +++ c:\dev\meld\meld-1.3.1\meldapp.py
    @@ -313,6 +313,7 @@
         defaults = {
             "window_size_x": prefs.Value(prefs.INT, 600),
             "window_size_y": prefs.Value(prefs.INT, 600),
    +        "window_maximized": prefs.Value(prefs.BOOL, 1),
             "use_custom_font": prefs.Value(prefs.BOOL,0),
             "custom_font": prefs.Value(prefs.STRING,"monospace, 14"),
             "tab_size": prefs.Value(prefs.INT, 4),
    

    И напоследок, применить настройку перед отображением окна:
    --- c:\dev\meld-base\meld-1.3.1\meldapp.py
    +++ c:\dev\meld\meld-1.3.1\meldapp.py
    @@ -499,6 +500,8 @@
             self.scheduler.connect("runnable", self.on_scheduler_runnable )
             self.widget.set_default_size(self.prefs.window_size_x, self.prefs.window_size_y)
             self.ui.ensure_update()
    +        if self.prefs.window_maximized:
    +            self.widget.maximize()
             self.widget.show()
             self.widget.connect('focus_in_event', self.on_focus_change)
             self.widget.connect('focus_out_event', self.on_focus_change)
    

  3. Некоторые настройки, как например стиль отображения панели инструментов, берутся из файлов конфигурации рабочего стола GNOME, а если их нету, используется настройка по-умолчанию. Для стиля панели инструментов это TOOLBAR_BOTH, т.е. отображение иконок и подписей.

    Для себя я просто поменял на TOOLBAR_ICONS:
    --- c:\dev\meld-base\meld-1.3.1\meldapp.py
    +++ c:\dev\meld\meld-1.3.1\meldapp.py
    @@ -375,7 +376,7 @@
    
         def get_toolbar_style(self):
             if not hasattr(self, "_gconf"):
    -            return gtk.TOOLBAR_BOTH
    +            return gtk.TOOLBAR_ICONS
             style = self._gconf.get_string('/desktop/gnome/interface/toolbar_style') or "both"
             style = {"both":gtk.TOOLBAR_BOTH, "text":gtk.TOOLBAR_TEXT,
                      "icon":gtk.TOOLBAR_ICONS, "icons":gtk.TOOLBAR_ICONS,
    

  4. Забавные вещи происходят при сохранении файлов с переносами отличными от LF (\n). В таком случае все LF заменяются на переносы файла, поэтому CRLF (\r\n) превращается в CRCRLF, а при следующем сохранении еще раз.

    Возможно проблема кроется в неправильном парсинге файла (в Ubuntu Meld себе такого не позволяет), но пока я решил ее, просто закомментировав участок кода, заменяющий одни переносы на другие:
    --- c:\dev\meld-base\meld-1.3.1\filediff.py
    +++ c:\dev\meld\meld-1.3.1\filediff.py
    @@ -815,6 +815,7 @@
                 else:
                     return melddoc.RESULT_ERROR
             text = buf.get_text(buf.get_start_iter(), buf.get_end_iter(), 0)
    +        """
             if bufdata.newlines:
                 if type(bufdata.newlines) == type(""):
                     if(bufdata.newlines) != '\n':
    @@ -832,6 +833,7 @@
                             if k != '\n':
                                 text = text.replace('\n', k)
                             break
    +        """
             if bufdata.encoding:
                 try:
                     text = text.encode(bufdata.encoding)
    

    Тем более, что этот же код все переносы ровняет под одну гребенку.

  5. В Meld'е установленном по инструкции на сайте GNOME, не доступны функции подсветки синтаксиса, отображения номеров строк и отображения пробелов вместо символов табуляции.

    Чтобы исправить это, я добавил в мануал библиотеку gtksourceview-2.2.2. В ней не хватает файлов language.rng, language2.rng и styles.rng, зато они есть в gtksourceview-2.9.3 в папке share\gtksourceview-2.0\language-specs. Их нужно просто скопировать в аналогичную в gtksourceview-2.2.2.
Теперь Meld ведет себя достаточно адекватно. Можно пользоваться.

Если кто-то будет применять на практике вышенаписанное, заглядывайте время от времени, возможно будут обновления.

P.S. Ранее не имел дела с python'ом, GTK и PyGTK, поэтому, если где-то написал откровенную ерунду, поправьте пожалуйста.
Tags:
Hubs:
+12
Comments 17
Comments Comments 17

Articles