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

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

SeeMe for Linux v1.0.2

SeeMe をまだ Delphi 5 という化石で作っていた頃の v2 画像が何故か出てきた。

seeme200

ナンジャコリャ…今になって見ると我ながら UI が古すぎる!
よくこんなのを恥ずかしげもなく公開していたものだ、信じられない。

XP のデザイン自体も古いけどウィジェットの絶対値配置ってマジ化石だな。
Vista や GNOME 環境を使っていると絶対値配置の奇妙なウイジェット位置に違和感出まくり。

PyGtk で GtkFixed コンテナを使っている初心者を最近見て死ぬほどガッカリしたんだが…
二年前の私はたいして変わらないな。

ということで今日の Python コード。

SeeMe for Linux で直接編集の指定部分。
何も書かれていなければ関連付け起動、でなければそのエディタで。
んでエディタを別プロセスで起動させたならそのまま SeeMe は終了。
というふうにしたかった、てか Windows 版がそうしている。

エディタ指定をしたならその実効ファイル名の引数に渡せばいいので普通なら下記…

os.system("%s %s" % (exe, self.sset.custome_path) )

これだと値が戻ってくるまで待機してしまう、つまり SeeMe はフリーズ状態に。
これでは使えない、ということで探したら os モジュールに spawn* というのがあるらしい。

16.1. os ? 雑多なオペレーティングシステムインタフェース ? Python v2.6.0 documentation

肝心な引数の書き方が可変個引数でよく解らない、検索してみたけどバラバラだし。
自分で色々試して二番目と三番目引数に実効ファイル名、四番目を開きたいファイルのフルパス

def on_textedit(self, widget, event=None):
    exe = self.deditor.edit_editor.get_text()
    if exe == "":
        os.system("xdg-open %s" % self.sset.custome_path)
        self.close()
    else:
        os.spawnlp(os.P_NOWAIT, exe , exe, self.sset.custome_path)
        self.close()

を入れてなんとか成功、イマイチ納得できないけどこれで動くからイイや!
ということで、Python で GUI アプリを作るのは難しい…
アトリビュート変数名の中身は本体スクリプトで、既に千行近くになっているけど…

ということで SeeMe for Linux v1.0.2 の公開。

追記

os.system("%s %s &" % (exe, self.sset.custome_path) )

こんな方法があった…出した直後に見つけるなよ俺。

SeeMe for Linux v1.0.1

昨日までは珍しく Vista のまま使って SeeMe のオンラインヘルプを書いていた。

SeeMe オンラインヘルプ @ はじめに – L’Isola di Niente

Windows 版のスクリーンショットを Aero 状態で行いたいんだもの。
Ubuntu は仮想でも見た目は変わらないので VirtualBox 上でいけるし。

Tab キーでのスニペット挿入が秀丸でも EmEditor でもできずもどかしい!
秀丸マクロのようなことが Gedit でできないとか思っていた頃があったのに。

スクリーンショットを撮っていて気がついた。
Linux 版の Welcome 説明文が beta のままだ!

seeme_linux_welcome

それと最初は国際化を狙っていたせいでエディタ部が英語のままだ!
ということで本日我がマシンを Ubuntu へ戻し for Linux の更新をしよう。
んでスクリーンショットの撮り直しだ。

イザやり始めるとアレもコレもやりたくなる。
全部 Windows 版の動作を再現及び移植だが Windows 版ってこんなに凝っていたっけ?
細かいことは本サイト ChangeLog で、それと IronPython 版との共通名化もやらなきゃ。

又今日も寝る時間が少なく…

SeeMe for Windows v4.0.1

あわわ、v4.0.0 はプロファイル編集ができないじゃんコレ。
ここは弄くっていないので前からか、まぁ普通はデフォルト位置で十分だし。

とはいえ放置もアレなので修正しようかどうか、そういえば

ぱぇぽぃ2 ? Blog Archive ? GetFullPath

のようにファイルドロップでフルパス指定にしようとして忘れていた!
なんたってそうすれば System.Windows.Form への参照を排除できる。
WPF なのに OpenFileDialog のためだけに WindowsForm を参照していたし。
よく見たら System.Xml.Linq まで…こんなの SeeMe で使っていないよ。

ということで AboutDlg のように上記 IronPython コードを C# 化…
しようと思ったけど面倒なのでハンドラの追記だけで済ませた。

ちなみに

ぱぇぽぃ2 ? Blog Archive ? WPF Hyperlink class for IronPython

の C# 化はこうやった。

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Text;
using System.Windows.Media;
using System.Collections.Generic;

namespace SeeMe4
{
    class About : Window
    {
        public About(Window owner)
        {
            this.Owner = owner;
            this.WindowStartupLocation = WindowStartupLocation.CenterOwner;
            this.Title = "About SeeMe for Windows";
            this.SizeToContent = SizeToContent.WidthAndHeight;
            this.ResizeMode = ResizeMode.NoResize;
            this.Icon = owner.Icon;
            // StackPanel
            var panel = new StackPanel();
            // Dialog Icon and Image
            var img = new Image();
            img.Source = owner.Icon;
            img.Width = 32;
            img.Height = 32;
            panel.Children.Add(img);
            // Create TextBlock List
            var v = new List<TextBlock>();
            for (int i = 0; i < 5; i++)
            {
                var b = new TextBlock();
                panel.Children.Add(b);
                v.Add(b);
            }
            v[0].Inlines.Add( new Bold(new Run("SeeMe for Windows 4.0.0\n")));
            v[1].Text = "Windows Version ( " + Environment.OSVersion.Version + " )";
            v[2].Text = "CLR Version ( " + Environment.Version.ToString() + " )\n";
            v[3].Text = "Copyright(c)2003-2009 by sasakima-nao";
            var url = new Hyperlink(new Run("http://palepoli.skr.jp/"));
            url.Click +=new RoutedEventHandler(url_Click);
            v[4].Inlines.Add(url);
            // Align Right button
            var btn = new Button();
            btn.Content = "Close";
            btn.Click += new RoutedEventHandler(btn_Click);
            DockPanel.SetDock(btn, Dock.Right);
            var dp = new DockPanel();
            dp.LastChildFill = false;
            dp.Children.Add(btn);
            panel.Children.Add(dp);
            // Append
            this.Content = panel;
        }

        void btn_Click(object sender, RoutedEventArgs e)
        {
            Close();
        }

        void url_Click(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Process.Start("http://palepoli.skr.jp/");
        }
    }
}

スクリーンショットを撮って気がついたが About のバージョンが 4.0.0 のままだ…
まあいいや、次の更新で直しておこう。

about_win

型指定がメンドクサイので var を使ったが何もかも IronPython より面倒。
中括弧とセミコロンと new と var が増えリストを System.Collections.Generic です。
特にハンドラ指定の RoutedEventHandler みたいなのってマジ書かなくてもよくないか?
こんなの Visual Studio エディタの助けが無かったら私は書けなかったかもだよ。

やっぱりこれからは IronPython だよ、EmEditor だけでデバッグもできるし。

WPF Hyperlink class for IronPython

SeeMe for Windows v4 beta2 のソースにコッソリ書いているが、
Hyperlink クラスをコードで作る方法が解らなかった。

Hyperlink クラス (System.Windows.Documents)

なんだよ、MSDN に普通に書いてあるや、どこを探していたのやら。
つまり Bold とかと同じように使えばいいということねん。

ぱぇぽぃ2 ? Blog Archive ? 初心者同然

よし、これで Linux 版の GtkAboutDialog と同じレイアウトにしてみる。
Windows 自体というか WPF だけでも専用ダイアログを用意してほしいんだが。

class AboutDlg(Window):
    """
        SeeMe About class
    """
    def __init__(self, owner, path):
        """
            Hyperlink, Run
            from System.Windows.Documents import *
        """
        self.Owner = owner
        self.path = path
        self.WindowStartupLocation = WindowStartupLocation.CenterOwner
        self.Title = "About SeeMe for Windows"
        self.SizeToContent = SizeToContent.WidthAndHeight
        self.ResizeMode = ResizeMode.NoResize
        self.Icon = BitmapFrame.Create(Uri(self.path + "\\img\\seeme.ico"))
        # StackPanel
        panel = StackPanel()
        # Dialog Icon and Image
        img = Image()
        img.Source = BitmapImage(Uri(self.path + "\\img\\seeme.ico"))
        img.Width = 32
        img.Height = 32
        panel.Children.Add(img)
        # Create TextBlock List
        v = []
        for i in range(5):
            b = TextBlock()
            panel.Children.Add(b)
            v.append(b)
        v[0].Inlines.Add(Bold(Run("SeeMe for Windows 5.0.0\n")))
        v[1].Text = "Windows Version ( %s )" % Environment.OSVersion.Version
        v[2].Text = sys.version + "\n"
        v[3].Text = "Copyright(c)2003-2009 by sasakima-nao"
        url = Hyperlink(Run("http://palepoli.skr.jp/"))
        url.Click += self.on_url
        v[4].Inlines.Add(url)
        # Align Right button
        btn = Button()
        btn.Content = "Close"
        btn.Click += self.on_exit
        DockPanel.SetDock(btn, Dock.Right)
        dp = DockPanel()
        dp.LastChildFill = False
        dp.Children.Add(btn)
        panel.Children.Add(dp)
        # Append
        self.Content = panel

    def on_url(self, sender, e):
        Diagnostics.Process.Start("http://palepoli.skr.jp/")

    def on_exit(self, sender, e):
        self.Close()

コレを Show() でオーナーウインドウから呼び出す

def on_about(self, sender, e):
    about = AboutDlg(self, self.path)
    about.Show()

about_dialog

ちょっとデザインが違うけど Windows ではこういう感じのほうが好まれそう。
WPF 使っているのに .NET 2.0 がどうのと出るのが少しだけ気に入らない。
つーかまだアルファにも達していないので自身のバージョン表記が滅茶苦茶だ。

とりあえず Hyperlink クラスの使い方はこれでオケのようだ。
たったコレだけのコードで About 完成、XAML ってマジで無駄だと思った。

今日はココしかやっていないのでバックアップはヤメとこう。