ll command and GtkSourceView3

Fedora 16 の update 通知があったので適用。
100 個もあるのか、まぁ chrome や flash も含まれていることだし。

PyGI が上書きされちゃったみたいだけど GBoxed 関連は修正されていた。
修正してくれたようで、放置されると疑ってごめんなさい。

ところで Fedora は ~/.bash_profile, ~/.bashrc どちらにもエイリアス指定が無い。
けど ll が通る、’ls -alF’ ではなく ‘ls -l’ のエイリアスのようだが。
Ubuntu から乗り換えて半年以上たつのに今頃違いに気がついた私って…

Ubuntu は ~/.bashrc で指定だけど Fedora はチト違うんだね。
てか Fedora は which コマンドのみで alias も探せるようにしているのか。
alias コマンドで充分だと思うけど。

【88】シェル(bash)を自分用にカスタマイズ【alias の覚書】 – 分室の分室

ついでに見つけたページ、lls は早速真似させていただくことにする。
Content Type でソートできれば拡張子もいらないけどさすがに無理か。

**********

ところで上画像のように Update に GtkSourceView があった。
何って Gedit や Anjuta の GTK+ 製エディタ部品そのものです。
テキストの DnD 編集で Gedit が落ちるのは、直っていなかった…

思いついた、コレを使って Gjot2 の代わりでも試しに作ってみようかなと。
Gedit のハイライト設定をパクれば表示は Gedit と同じになって便利かも。

API ドキュメントは以下にある。
GtkSourceView 3 Reference Manual

PyGI からは GtkSource の import で使える。
とりあえず基本読み書きと行番号表示のみの最小限コード。

#!/usr/bin/env python
#-*- coding:utf-8 -*-

from gi.repository import Gtk, Gio, Gdk, GtkSource

class TextEditor(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)
        # GtkUIManager and GtkAccelGroup
        self.uimanager = Gtk.UIManager()
        accelgroup = self.uimanager.get_accel_group()
        self.add_accel_group(accelgroup)
        # GtkActionGroup
        self.actiongroup = Gtk.ActionGroup("editor_menu")
        # GtkActionEntry
        ae = [  ("open", Gtk.STOCK_OPEN, "_Open", "<Control>O", "open", self.on_open),
                ("save", Gtk.STOCK_SAVE, "_Save", "<Control>S", "save", self.on_save),
                ("save_as", Gtk.STOCK_SAVE_AS, "Save as...", "<Shift><Control>S", "save as", self.on_save_as),
                ("quit", Gtk.STOCK_QUIT, "Quit", "<Control>Q", "quit", self.on_quit),
                ("file", None, "_File") ]
        self.actiongroup.add_actions(ae)
        self.uimanager.insert_action_group(self.actiongroup, 0)
        self.uimanager.add_ui_from_string(menu_xml)
        # MenuBar
        menubar = self.uimanager.get_widget('/MenuBar')
        # Toolbar and Style
        toolbar = self.uimanager.get_widget('/ToolBar')
        toolbar.set_style(Gtk.ToolbarStyle.ICONS)
        style = toolbar.get_style_context()
        Gtk.StyleContext.add_class(style, Gtk.STYLE_CLASS_PRIMARY_TOOLBAR)
        # StatusBar
        statusbar = Gtk.Statusbar()
        #
        #
        # Create GtkSourceView
        self.view = GtkSource.View()
        # Show Line Number
        self.view.set_show_line_numbers(True)
        #
        #
        # Add
        sw = Gtk.ScrolledWindow()
        sw.add(self.view)
        vbox = Gtk.VBox()
        vbox.pack_start(menubar, False, True, 0)
        vbox.pack_start(toolbar, False, True, 0)
        vbox.pack_start(sw, True, True, 0)
        vbox.pack_start(statusbar, False, True, 0)
        self.add(vbox)
        # self
        self.open_filename = ""
        self.resize(300, 300)
        self.set_title("Text Editor")
        self.show_all()
        self.set_focus(self.view)

    def on_open(self, widget, data=None):
        dlg = Gtk.FileChooserDialog(
                "Open File",
                self,
                Gtk.FileChooserAction.OPEN,
                (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, 
                Gtk.STOCK_OPEN, Gtk.ResponseType.ACCEPT))
        r = dlg.run()
        if r == Gtk.ResponseType.ACCEPT:
            self.open_filename = dlg.get_filename()
            f = open(self.open_filename, "r")
            t = f.read()
            f.close()
            buf = self.view.get_buffer()
            buf.set_text(t)
        dlg.destroy()

    def on_save(self, widget, data=None):
        if self.open_filename == "":
            self.on_save_as(widget)
        else:
            buf = self.view.get_buffer()
            t = buf.get_text(buf.get_start_iter(), buf.get_end_iter(), False)
            f = open(self.open_filename, "w")
            f.write(t)
            f.close()

    def on_save_as(self, widget, data=None):
        dlg = Gtk.FileChooserDialog(
                "Save File",
                self,
                Gtk.FileChooserAction.SAVE,
                (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, 
                Gtk.STOCK_SAVE, Gtk.ResponseType.ACCEPT))
        r = dlg.run()
        if r == Gtk.ResponseType.ACCEPT:
            buf = self.view.get_buffer()
            t = buf.get_text(buf.get_start_iter(), buf.get_end_iter(), False)
            self.open_filename = dlg.get_filename()
            f = open(self.open_filename, "w")
            f.write(t)
            f.close()
        dlg.destroy()

    def on_quit(self, widget, data=None):
        self.emit("destroy")

menu_xml = """<ui>
    <menubar name="MenuBar">
        <menu action="file">
            <menuitem action="open"/>
            <menuitem action="save"/>
            <menuitem action="save_as"/>
            <separator/>
            <menuitem action="quit"/>
        </menu>
    </menubar>
    <toolbar name="ToolBar">
        <toolitem action="open"/>
        <toolitem action="save"/>
    </toolbar>
</ui>"""

class App(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(
                self,
                application_id="apps.test.editor",
                flags=Gio.ApplicationFlags.FLAGS_NONE)
        self.connect("activate", self.on_activate)
        
    def on_activate(self, data=None):
        w = TextEditor()
        w.set_application(self)
    
if __name__ == "__main__":
    app = App()
    app.run(None)

FileChooserDialog の save で WARNNING が出て困っていたけど…
Gedit でも出るヤン、FileChooserDialog 自体のバグだろう。

読み書きに関しては Gio を使うべきなんだろうけど今はワカンネ!
これで問題なく読み書きできるから充分かと。

ついでに今頃解ったけど destroy を emit すれば閉じることができる。
GtkApplication が管理するので delete-event は使えない。

しかし GtkSourceView のみなら DnD 編集しても落っこちないのね。
Gedit 側のバグだったみたい、とにかく気長に修正待ちするけど。

ということで Gedit と同じ行番号表示ができるエディタでっきあっがりぃ。

コレを上手く使って Gjot2 の代わりっぽいを作りたいな。
平書きな Python コードも既に 1000 個を越えているしもっとまとめたい。
っっってその大半が PyGtk のコード、PyGI に書き直しメンドクセ!
まあその財産があるからこんなコードが数時間で書けるのであるが。