geditのプラグイン書きました

f:id:hashkun:20180924142457p:plain

 geditで文字数をカウントしてボトムパネルに表示してくれるプラグインを書いた。
 geditのプラグインを書く人が少なくて資料を探すのに少し苦労した。

2019/03/25 修正
 ツールメニューから無効化したプラグインが消えず白抜きになるバグがあったため、docinfo.pyを修正した。

  • 環境

Ubuntu 18.04.1 LTS
・gedit 3.28.1
・python3.6.6

・*.plugin:プラグインの情報を書いたファイル
・*.py:プラグインの動作(ソースコード)を書いたファイル
(*は同名)
の2つのファイルで構成され、その2つのファイルを~/.local/share/gedit/plugins/のディレクトリに置くことでプラグインとしてgeditに読み込まれる。読み込みはgeditの起動時に行われるので、書き直すたびにgeditを再起動していた(めんどい)

 プラグインは編集しているタブのテキストファイルの文字数をカウントし、ボトムパネルに表示するというもの。
 最低限の表示する機能しか書いていないので、見栄えは無視。

・docinfo.plugin

[Plugin]
Loader=python3
Module=docinfo
IAge=3
Name=docinfo
Name[ja]=ドキュメント情報パネル(docinfo)
Description=plugin docinfo
Description[ja]=ドキュメント情報をパネルに表示する
Authors=hashkun
Copyright=Copyright © 2018 hashmkr
Website=

・docinfo.py

"""
 ボトムパネルにドキュメントの統計情報を表示する
"""

#-*- coding:utf-8 -*-
import os
import gi

gi.require_version('Gtk', '3.0')
gi.require_version('Gedit', '3.0')

from gi.repository import GObject, Gedit, Gtk, Gio

class DocinfoAppActivatable(GObject.Object, Gedit.AppActivatable):
    
    app = GObject.property(type=Gedit.App)
    
    def __init__(self):
        GObject.Object.__init__(self)

    def do_activate(self):
        item = Gio.MenuItem.new("docinfo",  "win.docinfo_act")
        #tools-sectionはメニューバーのツールメニュー
        self.menu_ext = self.extend_menu("tools-section")
        self.menu_ext.append_menu_item(item)

    def do_deactivate(self):
        pass

class DocinfoWindowActivatable(GObject.Object, Gedit.WindowActivatable):

    __gtype_name__ = "Docinfo"
    window = GObject.property(type=Gedit.Window)

    def __init__(self):
        GObject.Object.__init__(self)
        self._bottom_panel  = None
        self._docinfo_label = None

    def do_activate(self):
        #ツールメニューの"docinfo"にon_panel()の紐付け
        action = Gio.SimpleAction.new("docinfo_act", None)
        action.connect('activate', self.visible_panel)
        self.window.add_action(action)
        
        icon = Gtk.Image.new_from_stock(Gtk.STOCK_YES, Gtk.IconSize.MENU)

        #labelを作ってbottom_panel
        self._docinfo_label = Gtk.Label("infolabel")
        self._bottom_panel  = self.window.get_bottom_panel()
        self._bottom_panel.add_titled(self._docinfo_label, "docinfo", "docinfo")

        self._docinfo_label.show_all()
        self._bottom_panel.set_visible_child(self._docinfo_label)
        
    def do_deactivate(self):
        self.window.remove_action("docinfo_act")
        self._docinfo_label.destroy()

    def do_update_state(self):
        self.update_panel()
            
    def visible_panel(self, action, data=None):
        status = not self._bottom_panel.get_property('visible')
        self._bottom_panel.set_property('visible', status)
    
    def update_panel(self):
        _bufcount = self.doc_info_get()
        self._docinfo_label.set_text('文字数:{}'.format(_bufcount))

    def doc_info_get(self):
        # この view が GtkSourceView
        _view = self.window.get_active_view()
        # この buf が GtkTextBuffer
        _buf = _view.get_buffer()
        #文字数を得る
        _bufcount = _buf.get_char_count()
        return _bufcount

 プログラムの大雑把な動作は、

  1. ツールメニューに追加するためのプラグインの項目を作成する
  2. 作成するときにアクションを紐付け
  3. プラグインの項目をツールメニューに追加

ここまでは、ツールメニューの動きで下からは文字数のカウントと表示の動作

  1. geditのボトムパネルのオブジェクトを取得
  2. 取得したパネルのオブジェクトにラベルオブジェクトを追加
  3. アクティブなタブのドキュメント情報を取得、その内のテキストバッファ(GtkTextBuffer)の文字数をカウントする
  4. 追加したラベルオブジェクトにカウントした文字数を表示させる
  5. カウントした文字数はシグナルdo_update_state()が発されるたび、更新される

 書いたプラグインのファイルを所定のディレクトリに置き再起動するとgeditの設定のプラグインタブに表示されるが、このときプラグインが白抜きになっている場合はちゃんと読み込まれていないので、ソースコードを見直そう。
 プラグインにチェックを入れて有効化するとメニューバー>ツールにdocinfoという項目が新しく追加されているので、それを押すと始めの画像のボトムパネルが表示される。もう一度docinfoを押すとボトムパネルは消える。

 初めてgeditのプラグインを作成したのだが、まあまあ実用的で良いんじゃないか?と思う。
 課題点としては文字数をカウントを行うところ(def doc_info_get(self)の_buf.get_char_count())では実は改行コードも一文字としてカウントしているので正確なカウントではないことと、Gtkラベルの位置がパネル内でセンターになっていることだ。
 機会があればまた書き直そうと思う。

  • 参考サイト

Gedit プラグインの作り方(v3.12 以降) - L'Isola di Niente
index.htm – gedit
How to write plugins for gedit · theawless
[gedit/wip/panels-as-stacks] Replace GeditPanel with GtkStacks.
6. Layout Containers — Python GTK+ 3 Tutorial 3.4 documentation
GitHub - footley/gedit-wordcount-plugin: A gedit plugin which adds a Label to the status bar with the active documents wordcount, where a word is definied as r"[a-zA-Z0-9]+[a-zA-Z0-9\-']*\s?"