g_idle_add

Gedit for Windows part3 | PaePoi
を少し改造しようと調べている時に g_idle_add という GLib の関数を知った。
筆者は何も知らないな、もっと勉強しなければいけないようだ。

何も処理を行っていないアイドル時にシグナルを送りつける。
ハンドラにて True を戻すとループ継続、False を戻すとループが止る。
g_timeout_add と同様みたい、ちとテスト。

#!/usr/bin/env python3

from gi.repository import Gtk, GLib

class IdleTest(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)
        self.connect("delete-event", Gtk.main_quit)
        self.label = Gtk.Label("0")
        button = Gtk.Button.new_with_label("Time consuming process")
        button.connect("clicked", self.on_clicked)
        vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
        vbox.pack_start(self.label, False, False, 0)
        vbox.pack_start(button, False, False, 0)
        self.add(vbox)
        self.show_all()
        # var
        self.count = 0
        # Idle
        GLib.idle_add(self.on_idle)

    def on_idle(self):
        if self.count == 1000000:
            return False
        self.count += 1
        self.label.set_text("{0}".format(self.count))
        return True

    def on_clicked(self, widget, data=None):
        s = ""
        for i in range(10000000):
            s += "homura"

IdleTest()
Gtk.main()

g_idle_add1

ボタンを押して何か処理を行っている最中は見事にシグナルは停止する。
なるほど、同一プロセスで何もしていない時だけシグナルが発生するのか。

#!/usr/bin/env python3

from gi.repository import Gtk, GLib

class IdleTest(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)
        self.connect("delete-event", Gtk.main_quit)
        self.label1 = Gtk.Label("0")
        self.label2 = Gtk.Label("0")
        vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
        vbox.pack_start(self.label1, False, False, 0)
        vbox.pack_start(self.label2, False, False, 0)
        self.add(vbox)
        self.show_all()
        # var
        self.count1 = 0
        self.count2 = 0
        # Idle
        GLib.idle_add(self.on_idle)

    def on_idle(self):
        if self.count1 == 100000:
            return False
        if self.count1 == 50000:
            GLib.idle_add(self.on_idle2)
        self.count1 += 1
        self.label1.set_text("{0}".format(self.count1))
        return True

    def on_idle2(self):
        if self.count2 == 100000:
            return False
        self.count2 += 1
        self.label2.set_text("{0}".format(self.count2))
        return True

IdleTest()
Gtk.main()

2 つ作成しても別スレッドとして動作するみたいですね。
上記のような使い方は CPU 負荷が凄いのでヤメたほうがいいと一応。

これがどういう時に便利かというと簡易スレッド分離。
ランチャを作成し、起動したことを書き出す。
そして終了コードを調べて表示したい等とする。

#!/usr/bin/env python3

from gi.repository import Gtk
import subprocess

class IdleTest(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)
        self.connect("delete-event", Gtk.main_quit)
        view = Gtk.TextView()
        view.set_size_request(200, 100)
        self.buf = view.get_buffer()
        button = Gtk.Button.new_with_label("gnome-calculator")
        button.connect("clicked", self.on_clicked)
        vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
        vbox.pack_start(view, True, True, 0)
        vbox.pack_end(button, False, False, 0)
        self.add(vbox)
        self.show_all()

    def on_clicked(self, widget, data=None):
        self.buf.set_text("Do gnome-calculator\n\n")
        #
        it = self.buf.get_end_iter()
        retcode = subprocess.call(["gnome-calculator"])
        if retcode == 0:
            self.buf.insert(it, "Sucsess")
        else:
            self.buf.insert(it, "Error: {0}".format(retcode))

IdleTest()
Gtk.main()

動きそうな気がするけど実際は on_clicked を抜けるまで何も書き出されない。
なので on_clicked にて g_idle_add を入れてスレッドを別にする。

#!/usr/bin/env python3

from gi.repository import Gtk, GLib
import subprocess

class IdleTest(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)
        self.connect("delete-event", Gtk.main_quit)
        view = Gtk.TextView()
        view.set_size_request(200, 100)
        self.buf = view.get_buffer()
        button = Gtk.Button.new_with_label("gnome-calculator")
        button.connect("clicked", self.on_clicked)
        vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
        vbox.pack_start(view, True, True, 0)
        vbox.pack_end(button, False, False, 0)
        self.add(vbox)
        self.show_all()

    def on_clicked(self, widget, data=None):
        self.buf.set_text("Do gnome-calculator\n\n")
        GLib.idle_add(self.on_idle)

    def on_idle(self):
        it = self.buf.get_end_iter()
        retcode = subprocess.call(["gnome-calculator"])
        if retcode == 0:
            self.buf.insert(it, "Sucsess")
        else:
            self.buf.insert(it, "Error: {0}".format(retcode))
        return False

IdleTest()
Gtk.main()

g_idle_add2

これなら on_clicked は抜けランチャの終了待機も問題なく行われる。
つまりいつ終るか解らない処理を待つ必要がある場合に利用できる。
こんな感じで簡易なスレッドが必要な場合はもうコレで充分ですよね。

Wnck

Libwnck Reference Manual
を試していて面白いことをみつけた。

#!/usr/bin/env python3

from gi.repository import Wnck

screen = Wnck.Screen.get_default()
''' output
(process:5006): Gdk-CRITICAL **: ...
'''

となる、おいおいどういうことだよ。

Part?II.?Getting Started with libwnck
に書いてある Python コードをそのまんま書いたのに。
下のほうにある C のコードを見ると

gdk_init (&argc, &argv);

とあるので Gdk.init(sys.argv) が必要なのかな?
なんて思って試してみると

#!/usr/bin/env python3

from gi.repository import Wnck, Gdk

screen = Wnck.Screen.get_default()

# Screen Size
x = screen.get_width()
y = screen.get_height()
print("Screen @ {0}x{1} pixel".format(x, y))

''' output
Screen @ 1920x1080 pixel
'''

なんだよ Gdk の import だけで普通に動く、使っていないのに。
そういえば Gtk を使う場合も init を呼ばずに使えている。
PyGI では Gdk の import だけで初期化は完了するということなのね。
Gtk の import でも同様になるみたい。

更に

#!/usr/bin/env python3

from gi.repository import Wnck, Gdk

screen = Wnck.Screen.get_default()

win = screen.get_active_window()
print(win.get_name())

''' output
AttributeError: 'NoneType' object has no attribute 'get_name'
'''

None って、やはりこれも C のコード同様に

#!/usr/bin/env python3

from gi.repository import Wnck, Gdk

screen = Wnck.Screen.get_default()

# Important
screen.force_update()

win = screen.get_active_window()
print(win.get_name())

WnckScreen を作成しただけでは動的な状況を把握できないようです。
しかし下のサンプルコードではこんな関数を呼んでいない。
mainloop を回すなら update は不要ということみたい。

しかし面白いことに

#!/usr/bin/env python3

from gi.repository import Gdk

screen = Gdk.Screen.get_default()

win = screen.get_active_window()
w = win.get_width()
h = win.get_height()
print("Active Window @ {0}x{1} pixel".format(w, h))

こっちだと active_window が得られる、よくわかんねぇ!
WnckScreen と GdkScreen は用途がまったく違うから実際の混乱は無いだろうけど。
Wnck はスクリーンの監視等が主な役目。
ということでサンプルコードの下側を GUIに改造してみた。

#!/usr/bin/env python3

# https://developer.gnome.org/libwnck/stable/getting-started.html
# to PyGI Window

from gi.repository import Wnck, Gtk

class ScreenMonitoring(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)
        self.connect("delete-event", Gtk.main_quit)
        # Wnck
        screen = Wnck.Screen.get_default()
        screen.connect("window-opened", self.on_window_opened)
        screen.connect("active-window-changed", self.on_active_window_changed)
        # View
        view = Gtk.TextView()
        self.buf = view.get_buffer()
        sw = Gtk.ScrolledWindow()
        sw.add(view)
        # Label
        self.label = Gtk.Label("active:")
        # Pack
        vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
        vbox.pack_start(sw, True, True, 0)
        vbox.pack_start(self.label, False, False, 0)
        self.add(vbox)
        self.resize(500, 200)
        self.show_all()

    def on_window_opened(self, screen, window, data=None):
        appname = window.get_application().get_name()
        title   = window.get_name()
        it = self.buf.get_end_iter()
        self.buf.insert(it, "{0}: {1}\n".format(appname, title))

    def on_active_window_changed(self, screen, previously_active_window, data=None):
        active_win = screen.get_active_window()
        if (active_win):
            self.label.set_text("active: {0}".format(active_win.get_name()))
        else:
            self.label.set_text("no active window")

ScreenMonitoring()
Gtk.main()

wncktest

機動後にアプリを立ち上げたりアクティブ状態を替えたりすると即座に反応する。
実はこのとき通知領域に clipoli を置いていたのだが認識しなかった。
Google Chrome は最小化していたけど認識、なるほど。

デスクトップはデスクトップというウインドウとして認識するのね
あと画像を見れば判るだろうけど筆者はデスクトップは desktop に変名している。
でも[デスクトップ]になる、Nautilus のサイドバーも変わらないしなんだろう?
Nautilus は[ファイル]にならないのに Eye of GNOME は[画像ビューアー]って何だよ。
Python アプリは get_application で python とはならないのか。

wnck_lubuntu

Lubuntu でも動くけど何故か Wnck が Warnimg を出しまくる。
desktop はキチンと変名、いやこのとき PCManFM で desktop を開いていた。
pcmanfm: pcmanfm がデスクトップのようだ、なんだこれ…
しかも何故か lxpanel を認識、GNOME と全然違うじゃないの。

なんかディストリビューションどころか環境ごとにバラバラになりそう。
上手く利用しないと Wnck はドハマリしそうな予感。

Gedit for Windows part3

Gedit Windows 版から IronPython を起動する。
Python コードを開いて F5 キーを叩くと実行結果をボトムパネルに表示。
Gedit で Python スクリプトを debug – L’Isola di Niente
つまりコレを再現したい。

Gedit の Windows 版で External Tools が使えないのでソースコードを見る。
ちなみに External Tools も Python 製である。
8.11 fcntl — fcntl() および ioctl() システムコール
を使っていた、なるほどこれでは Windows では使えないわけだ。

前回は少し勘違いをしていたようで環境変数は External Tools が登録するようだ。
何にせよ Linux と Windows でまったく同じコードというのは不可能だよね。

とりあえず Python なんだから subprocess でなんとかならないか。
window オブジェクトからロケーションは得られるのだから強引にでも。

と思ってこんなプラグインを作ってみた。

ipyexec.gedit-plugin

[Gedit Plugin]
Loader=python
Module=ipyexec
IAge=2
Name=Iron Python Execute
Description=Iron Python Execute
Authors=sasakima-nao <sasakimanao@gmail.com>
Copyright=Copyright © 2013 sasakima-nao <sasakimanao@gmail.com>
Website=http://palepoli.skr.jp/

ipyexec.py

#-*- coding:utf-8 -*-

import gedit
import gtk
import os
import subprocess

IPYPATH = "C:\Program Files (x86)\IronPython 2.7\ipyw64.exe"

ui_str = """<ui>
    <menubar name="MenuBar">
        <menu name="ToolsMenu" action="Tools">
            <menuitem name="ipyexec" action="ipyexec"/>
        </menu>
    </menubar>
</ui>
"""

class IpyExecPlugin(gedit.Plugin):
    def __init__(self):
        gedit.Plugin.__init__(self)

    def activate(self, window):
        self._window = window
        manager = self._window.get_ui_manager()
        self._action_group = gtk.ActionGroup("IpyExecActions")
        # GtkActionEntry
        # name, stock_id, label, accelerator, tooltip, callback
        actions = [("ipyexec", None, "ipyexec", "F5", "ipyexec", self.on_ipyexec_activate)]
        self._action_group.add_actions(actions)
        manager.insert_action_group(self._action_group, -1)
        self._ui_id = manager.add_ui_from_string(ui_str)
        # Panel
        self.textview = gtk.TextView()
        self.textview.show()
        self.outputpanel = gtk.ScrolledWindow()
        self.outputpanel.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        self.outputpanel.set_shadow_type(gtk.SHADOW_IN)
        self.outputpanel.show()
        self.outputpanel.add(self.textview)
        bottom = self._window.get_bottom_panel()
        bottom.add_item(self.outputpanel, "Output", "Output")

    def deactivate(self, window):
        manager = self._window.get_ui_manager()
        manager.remove_ui(self._ui_id)
        manager.remove_action_group(self._action_group)
        manager.ensure_update()
        # Panel
        bottom = self._window.get_bottom_panel()
        bottom.remove_item(self.outputpanel)

    def update_ui(self, window):
        pass

    def on_ipyexec_activate(self, action):
        # Show Buttom Panel
        bottom = self._window.get_bottom_panel()
        bottom.show()
        # Buffer
        buf = self.textview.get_buffer()
        # Get full path
        view = self._window.get_active_view()
        doc = view.get_buffer()
        location = doc.get_location()
        path = location.get_path()
        # Popen
        popen = subprocess.Popen(
                [IPYPATH, path],
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE )
        output = popen.communicate()
        if output[1]:
            buf.set_text("Do IronPython\n\n%s\nDone." % output[1])
        else:
            if output[0]:
                buf.set_text("Do IronPython\n\n%s\nDone." % output[0])
            else:
                buf.set_text("Do IronPython\n\nNo Output\n\nDone.")

ipyexec

なんとか動く、かなり手抜きくさいのはご了承。
External Tools と違って終了するまで値が戻ってこない仕様ですんで。

小物ならコレで問題ないけど Application クラスを使うとなると…
即座に stderr を検知したいけど、手段が解らないです。

拡張子判別をしてアプリを振り分ける手もあるけど私的にはコレでいい。
別の言語で起動させたい人はお好みに書き換えてください。

これ以上改造するにしても、GTK2, gconf, Python2, PyGtk…
本体及びプラグインの構成部品がことごとく既に開発終了しているという現実がね。
Gedit3 の Windows パッケージが出るならもう少し本気になるかも。

ということで。
Linux でも Windows でも動くことを考慮しなければプラグインは作れます。
ただ Windows で PyGtk を勉強しても他で何も役に立たない、しかも開発終了品。
なので他人に勧め辛いのが難点、Python の勉強にはなるけど。
もっとイイのを誰かに作ってほしいな(ぉい!

# 2013.11.09 追記
日本語出力ができなかった、日本語 Windows の stdout は cp932 なので変換。
それと output を別スレッドにして動作を判り易く改良してみた。
終了まで出力しないのは変わらないけど。

#-*- coding:utf8 -*-

import gedit
import gtk
import os
import subprocess
import glib

IPYPATH = "C:\Program Files (x86)\IronPython 2.7\ipyw64.exe"

ui_str = """<ui>
    <menubar name="MenuBar">
        <menu name="ToolsMenu" action="Tools">
            <menuitem name="ipyexec" action="ipyexec"/>
        </menu>
    </menubar>
</ui>
"""

class IpyExecPlugin(gedit.Plugin):
    def __init__(self):
        gedit.Plugin.__init__(self)

    def activate(self, window):
        self._window = window
        manager = self._window.get_ui_manager()
        self._action_group = gtk.ActionGroup("IpyExecActions")
        # GtkActionEntry
        # name, stock_id, label, accelerator, tooltip, callback
        actions = [("ipyexec", None, "ipyexec", "F5", "ipyexec", self.on_ipyexec_activate)]
        self._action_group.add_actions(actions)
        manager.insert_action_group(self._action_group, -1)
        self._ui_id = manager.add_ui_from_string(ui_str)
        # Panel
        self.textview = gtk.TextView()
        self.textview.show()
        self.outputpanel = gtk.ScrolledWindow()
        self.outputpanel.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        self.outputpanel.set_shadow_type(gtk.SHADOW_IN)
        self.outputpanel.show()
        self.outputpanel.add(self.textview)
        bottom = self._window.get_bottom_panel()
        bottom.add_item(self.outputpanel, "Output", "Output")

    def deactivate(self, window):
        manager = self._window.get_ui_manager()
        manager.remove_ui(self._ui_id)
        manager.remove_action_group(self._action_group)
        manager.ensure_update()
        # Panel
        bottom = self._window.get_bottom_panel()
        bottom.remove_item(self.outputpanel)

    def update_ui(self, window):
        pass

    def on_ipyexec_activate(self, action):
        # Show Buttom Panel
        bottom = self._window.get_bottom_panel()
        bottom.show()
        # Write
        buf = self.textview.get_buffer()
        buf.set_text("Do IronPython\n\n")
        glib.idle_add(self.on_idle)

    def on_idle(self):
        # Buffer
        buf = self.textview.get_buffer()
        it = buf.get_end_iter()
        # Get full path
        view = self._window.get_active_view()
        doc = view.get_buffer()
        location = doc.get_location()
        path = location.get_path()
        # Popen
        popen = subprocess.Popen(
                [IPYPATH, path],
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE )
        output = popen.communicate()
        if output[1]:
            buf.insert(it, "%s\nError." % output[1])
        elif output[0]:
            #buf.insert(it, "%s\nDone." % output[0])
            s = unicode(output[0], encoding='cp932').encode("utf8")
            buf.insert(it, "%s\nDone." % s)
        else:
            buf.insert(it, "Done.")
        return False

####################

Gedit には grep 機能が無い?
元が Linux のエディタだよ、皆 grep コマンドを使っているからあるわけない。

だから WindowsPowerShell で Select-String コマンドを使いなさい。
つか grep というエイリアスを作ることもできる。
Windows PowerShell の機能

mkdir WindowsPowerShell
cd WindowsPowerShell
echo Set-Alias grep Select-String > Microsoft.PowerShell_profile.ps1

ドキュメントディレクトリでこんなバッチを動かせば一発よん。

grep

パイプによる stdout も受け付けるし grep コマンドとほぼ同様。
まさか Gedit で grep プラグインを探している偽 Linux 使いはいませんよね。

Gedit for Windows part2

さてプラグインだが。
プラグインはほとんど Python で作られているのはご存知のとおり。
このマシンでは IronPython しか入れていないのだが。
同梱の組込 Python2.6 でプラグインを動かすということみたい。

Python で作られているコードスニペットプラグインを有効にする。
拡張子を py にしたファイルを開き py と打ち込んで Tab キーを叩く。

gedit_py

キチンと動作する、Python2 を別途で用意する必要は無いようだ。
つか EmEditor の外部ツールと違ってバカ早い、

って、だから Windows ではテキストファイルの一行目に特別な意味なんて無い。
@Linux では実行パーミッション時に一行目プログラムで動かす、拡張子は無意味
本当に Linux のものを Windows で動かせるようにしただけなんだとよく判る例。

ちなみにスニペットを変更すると

%USERPROFILE%\.gnome2\gedit\snippets

に変更データが入る、なるほど Linux と同じなんだ。

どうでもいいけど Explorer ではドットで始まる名前のファイルが作れない。
MKDIR コマンドなら作れる、大きなお世話だ。

ならばプラグインも
%USERPROFILE%\.gnome2\gedit\pligins
でイケそうなのに認識してくれない。

Gedit – Tutorials – SCOL Language

うーん、Program Files (x86) 以下に入れるしか手段が無いみたいだ。
%PROGRAMFILES(X86)%\gedit\lib\gedit-2\plugins

programfiles

しかたがないので管理者権限で Explorer を起動。
以下の自作プラグインをひたすらコピー、Gedit2 だから v1 のほうね。
Gedit 及び Eye of Gnome プラグイン

おぉ動く、LFonBR は CRLF だと CR 部が改行されちゃうけどね。
とりあえず Linux 依存(パス区切り等)の部分が無いなら動くのね。

しかし External tools が無いのは痛い。

Apps/Gedit/Plugins – GNOME Wiki!

標準にあるはずなんだが、External tools の More を見る。
GLib からでは環境変数が登録できないってことかな。
面倒くさいけどチェックするプラグインでもテキトーに作るか。

test.gedit-plugin

[Gedit Plugin]
Loader=python
Module=test
IAge=2
Name=Test
Name[ja]=テスト
Description=test
Description[ja]=テスト
Authors=sasakima-nao 
Copyright=Copyright © 2009 sasakima-nao 
Website=http://palepoli.skr.jp/

test.py

#-*- coding:utf-8 -*-

import gedit
import gtk
import os

ui_str = """<ui>
	<menubar name="MenuBar">
		<menu name="EditMenu" action="Edit">
			<placeholder name="EditOps_3">
				<menuitem name="test" action="test"/>
			</placeholder>
		</menu>
	</menubar>
</ui>
"""

class HtmlEscapePlugin(gedit.Plugin):
	def __init__(self):
		gedit.Plugin.__init__(self)

	def activate(self, window):
		self._window = window
		manager = self._window.get_ui_manager()
		self._action_group = gtk.ActionGroup("TestActions")
		# GtkActionEntry
		# name, stock_id, label, accelerator, tooltip, callback
		actions = [("test", None, "test", None, "test", self.on_test_activate)]
		self._action_group.add_actions(actions)
		manager.insert_action_group(self._action_group, -1)
		self._ui_id = manager.add_ui_from_string(ui_str)
		
	def deactivate(self, window):
		manager = self._window.get_ui_manager()
		manager.remove_ui(self._ui_id)
		manager.remove_action_group(self._action_group)
		manager.ensure_update()
		

	def update_ui(self, window):
		pass
	
	def on_test_activate(self, action):
		# Check
		s = os.environ["USERNAME"]
		self.messagebox(s)
		try:
			# echo %GEDIT_CURRENT_DOCUMENT_PATH%
			s = os.environ["GEDIT_CURRENT_DOCUMENT_PATH"]
			self.messagebox(s)
		except:
			self.messagebox("No %GEDIT_CURRENT_DOCUMENT_PATH%")
		
	def messagebox(self, text):
		dlg = gtk.MessageDialog(self._window,  
								gtk.DIALOG_MODAL,  
								gtk.MESSAGE_WARNING, 
								gtk.BUTTONS_OK,  
								text)  
		r = dlg.run()  
		dlg.destroy()

error

あぁやっぱり。
これじゃ自力でも外部ツールは作れないよ。
IronPython をエディタから起動したかったんだが困った。

Gedit for Windows part1

久しぶりに Windows を使う。
何気に EmEditor pro 版のバージョンアップを始める。
ライセンスの更新をって、以前の登録キーって何だっけ?
マジで解らない事態に、Windows を使わなさすぎだ。

探したり問い合わせしたりするほど使っていないし。
ならばもういいや削除しよう、で。

代わりに秀丸を使ってみたがなんとも使いにくい。
Shift+Tab で逆インデントする手段が無いしスニペット機能も無い。
設定が多すぎてゲンナリ、よくこんなのを昔は愛用していたなと。
EmEditor の設定はもっとゴチャゴチャしていたけど。

特に Shift+Tab ができないと IronPython コードを書くのに困る。
逆インデントに BackSpace を 4 回叩くなんてやってられねぇ。
EmEditor でもマクロで強引にやっていただけだし。

あーあ、Gedit に慣れ過ぎだな筆者は。
と長い前置きはこれくらいにして。

ということで、Gedit の Windows 版を試すことにした。

gedit

gedit win32 binary にリンクがある、2.30 かよ。
Linux 版は現在 3.10 だよ。
なんか 23MB もあるし、なんでこんなにデカいのだ?

インストールしてみて驚く、GTK+, ORBit どころか Python2 まで同梱なのか。
そりゃデカくて当然。

gedit_dir

起動するとホームに .gconf, .gconfd というディレクトリが作られる。
ORBit があるし設定読み書き方法も gconf のまま Win32 化したんだね。
だから Windows でドットディレクトリは無意味だというのに。

【レビュー】世界のテキストエディターから – LinuxテキストエディターのWindows版「Gedit」 (1) Windows OSでGeditを使う | マイナビニュース

上記がエディタヲタ向けにうまくまとめていると思う。
色分けとかばかり気にして検索機能ガン無視の人ばかりだからね。

さて実際の利用ではどんな感じか。

起動遅すぎ、おまえは IronPython か!
いや、たまにしか使わないから SuperFetch は無効にしているんですけど。
とにかく秀丸と併用だとイヤでも差が気になる。

Shift+Tab は、当然のように使える。

DnD 編集も可能、やっぱり GtkSourceView だね。

デフォルト読み書きは当然 UTF-8 だが改行は CRLF になっている。
LF でもいいんだが、LF だとメモ帖で改行してくれないからだろうな。
とにかく CP932 はもう抹殺してくれ、マジでウンザリ。

外部ツールプラグインが見当たらない、あれ?

ヘルプでエラー、まさか devhelp が必要なの?

ダイアログを出してもエディタ部をホイールスクロールできる。
Windows は大抵コレができなくてもどかしいのでうれしい。
でも非アクティブではスクロールできない、GNOME とは少し違う。

プレーンテキストの保存は自分で txt の拡張子を付ける必要がある。
Linux なら常識というか拡張子なんて見分けやすい程度の意味しか無いし。

gedit_find

検索は Ctrl+F でダイアログ、Ctrl+G で次を検索。
うん Linux と同じだ、Gedit3 のニョッキのほうが使いやすいが。

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

f = open("azu.txt", "w")
a = u"あずにゃんはかわいい\n".encode("utf8")
s = ""
for i in range(10000):
    s += a

f.write(s)
f.close()

こんなコードで IronPython から一万行のテキストファイルを作成。
読み込み速度は、おぉシーケンシャルで読み込むようで滅茶苦茶早い。
全置換なんて一瞬、なんと秀丸より早い。

zenchikan

十分使えるレベルというより恐るべし潜在能力だった。
プラグイン等については次回(多分)