Gedit」タグアーカイブ

Ctrl+Space

先日の Update から Fedora 15 のキーボードで「全角/半角」キーが使えない。
検索すると全員か、私は素直に Ctrl+Space を利用しながら気長に修正を待つよ。

ところで Ctrl+Space って Gedit のスニペット挿入ショートカットだったんだが。
ついでに Visual Studio や monodevelop のコード保管もこのキー。

なので GNOME 2 の頃は iBus の設定からこのキーを削除するのが儀式だったんだけど…
iBus の設定に無いし Gedit もまったく反応しない、どうなっているの…
Ubuntu 11.04 の Gedit 2 は変わっていないな、GNOME 3 ではどこで指定するのだ?

追記
2011.07.10 のアップデートで以前の方式に戻したっぽい、反応は鈍くなったけど。
というか Ctrl+Space がデフォルトで利用できなくなって Gedit で使えるように。
自分で iBus の設定を加える必要があるみたい。

更に追記 2011.07.14 のアップデート
Zenkaku_Hankaku から Releace を外さないと認識しなくなっている…
製作者も迷走しているのだろうか、ごくろうさま。

追記おわり

Common F15 bugs – FedoraProject

なんとかならないかと色々探したり試したりしていて発見。
試しに昔懐かしい Alt+「全角/半角」 を何気に押してみたら

複数タブは無理だけど複数ウインドウならこのキーで選択できる。
英語キーボードは持っていないから解らないけど、もしかしてこの機能が影響している?

キーコードを調べるのに xev というコマンドがある。

端末から起動して何かシグナルが発生すると標準出力に吐き出される。
Zenkaku_Hankaku はしっかり認識しているのか、キーコードが原因では無いな。
というか xev って便利だな、なるほどこんなシグナルが発生しているのね。
今後のアプリ開発に利用させてもらおう。

ついでに
/etc/X11/xorg.conf.d/00-system-setup-keyboard.conf
/etc/sysconfig/keyboard
どちらも jp106 なのに

$ setxkbmap -print
xkb_keymap {
	xkb_keycodes  { include "evdev+aliases(qwerty)"	};
	xkb_types     { include "complete"	};
	xkb_compat    { include "complete+japan"	};
	xkb_symbols   { include "pc+jp+inet(evdev)+terminate(ctrl_alt_bksp)"	};
	xkb_geometry  { include "pc(pc104)"	};
};

となるのだがコレらは無視され evdev というものが自動認識するらしい。
Ubuntu の頃は自動認識に問題が何もなかったので調べようとも思った事が無かった。

/usr/share/X11/xkb/keycodes/evdev
が割り当て表みたい、よくある CapsLock と Ctrl を入れ替えるには

$ beesu gedit /usr/share/X11/xkb/keycodes/evdev

で開いて 37 と 66 を入れ替えて再ログインすればイケた、なるほど。
xmodmap とかはもうどうでもいいんだね。

cat /proc/bus/input/devices
でマウスやキーボード等のデバイスを確認できる。

無線マウスのレシーバであるとかも解るのか、なるほど。
解決はしなかったけどおかげで色々と知ることがあってよかった。

でもやっぱり Ctrl+Space では慣れていなくて間違える…

Fedora 15 006

Fedora 15 (GNOME 3) 64bit 生活六日目。

※ Gedit Plugin

Gedit/PythonPluginHowTo – GNOME Live!

Gedit 3 のプラグインは妙に複雑になった感じだけどやってみると簡単。
Gedit プラグインの作り方 – L’Isola di Niente
私の公開しているこのページを Gedit 3 用に改造してみる。

*.gedit-plugin 拡張子であったファイルは *.plugin と拡張子を変更。
セクション名を [Plugin] に、IAge を 3 に変更、v2 との違いはコレだけだ。

肝心のコード

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

import gedit
import gtk

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

    def activate(self, window):
        self.window = window

    def deactivate(self, window):
        pass

    def update_ui(self, window):
        pass

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

from gi.repository import GObject, Gedit, Gtk

class TestPligin(GObject.Object, Gedit.WindowActivatable):
    __gtype_name__ = "TestPligin"
    window = GObject.property(type=Gedit.Window)
    def __init__(self):
        GObject.Object.__init__(self)

    def do_activate(self):
        pass
        
    def do_deactivate(self):
        pass

    def do_update_state(self):
        pass

ということみたい、コールバックに引数は無くなったんだね。
__gtype_name__ は class 名と同じにしなければいけないみたい。

多重継承の敬称元を Gedit.AppActivatable とか3つから選べになっている。
普通なら Gedit.WindowActivatable だけでいいだろう。
下のほうにあるサンプルコードは継承元を書き忘れているじゃん…

後は self.window のメソッドを辿って弄くっていく。
v2 のコードから gtk → Gtk に全置換する必要がある。
それと activate のコールバックは引数を3つにしておく必要があった。
user_data を指定しなくても None が送られてくるみたい、注意ね。

ついでに GtkMessageDialog の引数は enum 形式に変更されていた。
指定がよく解らない人は dir() で辿って(私はそうやった)

testtest.plugin

[Plugin]
Loader=python
Module=testtest
IAge=3
Name=testtest
Name[ja]=テストテスト
Description=plugin test
Description[ja]=プラグインのテスト
Authors=sasakima-nao 
Copyright=Copyright © 2011 sasakima-nao 
Website=http://palepoli.skr.jp/

testtest.py

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

from gi.repository import GObject, Gedit, Gtk

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

class TestTest(GObject.Object, Gedit.WindowActivatable):
    __gtype_name__ = "TestTest"
    window = GObject.property(type=Gedit.Window)
    def __init__(self):
        GObject.Object.__init__(self)

    def do_activate(self):
        # GtkUIManager を得る
        manager = self.window.get_ui_manager()
        # GtkActionGroup を新規で作成
        self._action_group = Gtk.ActionGroup("TestTestActions")
        # GtkActionEntry を作成
        # name, stock_id, label, accelerator, tooltip, callback
        actions = [("testtest", None, "引用に変換", None, "すてーたすばー", self.on_testtest_activate)]
        # GtkActionGroup に挿入
        self._action_group.add_actions(actions)
        # GtkUIManager に追加
        manager.insert_action_group(self._action_group, -1)
        self._ui_id = manager.add_ui_from_string(ui_str)
        
    def do_deactivate(self):
        manager = self.window.get_ui_manager()
        manager.remove_ui(self._ui_id)
        manager.remove_action_group(self._action_group)
        manager.ensure_update()
        

    def do_update_state(self):
        pass
    
    def on_testtest_activate(self, action, data=None):
        view = self.window.get_active_view()
        buf = view.get_buffer()
        try:
            begin, end = buf.get_selection_bounds()
        except:
            self.messagebox("変換したいテキストを選択してください")
            return
        text = begin.get_text(end)
        lines = text.split("\n")
        # list の join に変更
        result = []
        for line in lines:
            result.append("> {0}".format(line))
        buf.delete_selection(True, True)
        buf.insert_at_cursor("\n".join(result))
            
        
    def messagebox(self, text):
        dlg = Gtk.MessageDialog(
                self.window,  
                Gtk.DialogFlags.MODAL,  
                Gtk.MessageType.WARNING, 
                Gtk.ButtonsType.OK,  
                text)  
        r = dlg.run()  
        dlg.destroy()

と2つのファイルを作成して ~/.local/share/gedit/plugins に置く。
Gedit を再起動して設定からこのプラグインを選択。

GtkUIManager のメソッドや XML UI 指定は v2 と変わっていないようだ。
これで Gedit 3 のプラグイン作りはなんとかなりそう。

ついでに、外部ツールで実行前にファイルを保存するように指定すると動作しない。
gedit って更新毎に必ず一ヶ所はおかしな所があるよね。

EmEditor を Gedit 風にカスタマイズ

以前
Tab キーでのスニペット挿入が秀丸でも EmEditor でもできずもどかしい!
なんて書いたけど…

窓の杜 – 【NEWS】スニペットの強化で入力作業が大幅に軽減された「EmEditor」v9のベータ版が公開

ぅおい! EmEditor v9 はできるんかい。
有償でも絶対に買うよ、会社なんだから無償バージョンアップを続けるのも辛いだろうし。
閉じ括弧の自動保管とかなんてウザいだけだからいらないんだが。
コード保管も使い物にならないだろうし、Visual Studio レベルなら考えるけど

よし、EmEditor を普段使っている Gedit 設定風にカスタマイズしてしまおう!

Ubuntu ではテキスト編集を全て Gedit で行っているのでもう手が勝手に動く私。
どうでもいいが最近 gEdit と書くか Gedit と書くかで迷うようになった。

まず Shift+Home で行の一番先頭まで選択してしまう件をなんとかしたい。

得に Python をやっているとインデントの先頭までを選択はよく行う。
Ctrl+Shift+Alt+Home でインデントの先頭になるけどコンナの普通に何度も押せるかい!
これは「ヘルプ – キーボードマップ」から

shift_home

と割付変更、これだけでインデントの先頭までを選択になる。
もう一度 Home を叩けば行の先頭へ、これで Gedit と完全に同じだ。

ぱぇぽぃ2 ? Blog Archive ? Home キーを 2 回叩け

それに Shift+Tab での逆インデントが範囲選択中しか行えないのが理解できない。
範囲選択されていなくてもその行を逆インデントしたほうが直感的だと思うんだが。
というか Python でコレができないのは致命的、半角スペース 4 つが普通なんだから。

ちなみに Linux の /usr/bin 以下にある Python スクリプトは全部半角スペース 4 つである。
Windows ならともかく Linux でこのインデント以外にて Python を書いている人は…略。
とにかく Shift+Tab で逆インデントしてくれないとスクリプトを書くのに効率が悪すぎる。

なのにキー割り当てに設定が無い、しかたがないのでマクロを作って Shift+Tab に割付。
Gedit はカーソル位置がどこでも逆インデントできるけど結局は先頭でしか行わない私。

if (document.selection.IsEmpty) {
	if (document.Config.Indent.InsertSpaces)
		document.selection.DeleteLeft(4);
	else
		document.selection.DeleteLeft(1);
} else {
	document.selection.UnIndent(1);
}

Python でなく js で書いているのは気にしない。
Windows 7 RC には IronPython しかインストールしていないからである。
とりあえずこれでインデントに対する私的な不満は無くなった。

gedit でデバッグ

んで、外部ツールに IronPython を登録してコチラも F5 に割り付けてと。

f5exec

Python の設定を開いて「タブ/インデント」はインデント開始文字を空に。
勝手にインデントしてしまうのが私は気に入らない、直感的でないものは極力排除。
タブの代わりに 4 つの空白を挿入に変更、これで望みどおりの動作になった。

後はスニペットに似たようなのをガシガシ登録。
でもスニペットだと認識するのに少し時間が掛かるみたい、改良を気長に待つとするか。

doc

しかしスニペットプラグインウインドウを表示した状態でないと使えない、残念。
常に有効状態にするには…

emeditor9b

こうするしかないかな、もう少し弄くってみます。
公開している(実際に私が利用している)Gedit プラグインと同様なマクロも書かねば。

追記

bg

スニペットのプロパティに
「バックグラウンドでも実行」
ってのがあった、チェックすれば常に有効になるみたい。

Shift-JIS で読み直しする gedit pligin

Windows から持ってきた Shift-JIS なテキストファイルを gEdit にドロップで開くと文字化け。
Cinema や minipoli のコードを「俺どう書いたっけ?」と自分で参考にする時が結構あるのよ。
もう慣れてしまったけど毎回毎回読み直しするのも面倒になってきた。

Gedit/PythonPluginHowTo – GNOME Live!

一旦破棄して gedit.Encoding 指定で読み込めばプラグインで作れそうだ。
create_tab_from_uri の引数で行ジャンプまで指定できるんだ、これは面白そう。

ということでさっき Shift-JIS で読み直しするプラグインをこさえて本サイト更新!
製作時間は一時間、あぁプラグインは楽でいい。

EUC-JP も考慮しようかと思ったけど私は現在 EUC-JP なファイルを持っていない…
それより意図的に私が作らないほうが「作ってみようかな?」という人が出てくるかも。
なんて思ったので Shift-JIS のみで公開することにした、手抜きじゃないですよ。

それと gEdit プラグインの応用 1 なんてページを増やした。
カーソル位置の GtkTextIter 取得方法くらいは解説しなきゃ誰も始められないかなと。
こんなのをチビチビ作っているが需要は微妙である。

次はサイドバーとかを使いたいんだが…アイデアが浮かばない。

GtkTextView って内部は UNICODE なのかな

ちょっと gEdit のプラグインを弄くっていたのでありますが。

13.3. Text Buffers

を見てカーソル位置の GtkTextIter を得て後は多分コレでイケるだろうと作っていた。
上手くいったからイイのだろう、で、面白いことを見つけた。

def on_hoge_activate(self, action):
    # バッファを得る
    view = self._window.get_active_view()
    buf = view.get_buffer()
    try:
        # カーソル位置の GtkTextIter 取得
        pos = buf.get_property("cursor-position")
        it = buf.get_iter_at_offset(pos)
        # 一つ前の文字を得る
        it1 = buf.get_iter_at_offset(pos-1)
        s = it1.get_char()
        if s == "\n":
            return
        # 必要な変数を初期化してループ
        count = pos
        itnext = None
        itend = buf.get_end_iter()
        s1 = ""
        while 1:
            # 次の GtkTextIter を得る
            count += 1
            itnext = buf.get_iter_at_offset(count)
            # EOF
            if itnext.equal(itend):
                break
            # 文字を得て比較
            s1 = itnext.get_char()
            #
            # 表示してみる
            print s1
            #
            if s1 == "\n" or s1 == "。":
                break
            elif s == s1:
                # ここまでの範囲を print
                itnext = buf.get_iter_at_offset(count)
                text = it.get_text(itnext)
                print text
                break
    except Exception, s:
        self.messagebox("%s" % s)

とまあ説明しやすく?書き換えたけどカーソル位置から特定範囲の文字列を得る。
具体的にはカーソルの直前文字と同じ文字を見つけたら抜き出すコードです。

これでイイの?
だって Ubuntu って UTF-8 だよ、アルファベットは 1 バイト、日本語は 2?3 バイト。
というか Windows で文字列を弄くる時に絶対に問題になるんですよ文字コードは。
いやまて、get_char() で char を取り出したって結局はポインタなんだし。
でも漢字とか混ぜると破壊されるわけで、内部はどうなるんだろう?

ということで上のように途中で char を抜いた部分にて print してみることにした。
アルファベットとひらがなカタカナ漢字記号を混ぜた文を作って実験。

atom

あれ、char 配列になっていないじゃん。
_ismbslead みたいなことをしているのか内部で UNICODE 化しているか知らないけど.。
これは楽だ、 gEdit プラグインでは UTF-8 であることを意識しないでいいようです。

どうでもいいけど char って character の略なので「キャラ」と読みますお。