Hatena::ブログ(Diary)

Koonies/こりゃいいな! このページをアンテナに追加 RSSフィード Twitter

2009 | 06 | 07 | 08 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 10 |
2011 | 01 | 02 | 05 | 06 | 07 | 08 | 09 |
2012 | 05 | 06 |

2012-06-11

Koonies2012-06-11

TortoiseHgのカスタムツールバーを設定する方法

TortoiseHg 2.4.1リリースされました。で、1つ前のバージョン2.4で追加されたカスタムツールバーはどうやって設定するのかずっと気になっていましたがようやく分かったのでメモを兼ねて、書いておきます。

設定方法

[tortoisehg-tools]

# Execute a mercurial command. These _MUST_ start with "hg"

# Note that we can use any built-in TortoiseHg icon

update_to_tip.command = hg update tip

update_to_tip.tooltip = Update to tip

update_to_tip.icon = hg-update

no title

上記のように設定ファイルへ[tortoisehg-tools]という項目を追加し、それに続けてコマンドの設定を書きます。それで書けたらソフトを再起動します。

.command必須で、.tooltip.iconオプション(無くても可)ということです。ちなみに上記の引用元のサイト記述例は

誤:update_to_tip.ico = hg-update

正:update_to_tip.icon = hg-update

という風にnが抜けているためアイコンが正しく設定できていないようです。

それとアイコンの設定にはicoファイルのフルパスの他、hg-updateのように内蔵アイコンも設定可能みたいです。これ以外にも下記のアイコンが使える模様。

(右上のスクリーンショットはコレの一覧)

application-exit

document-new

edit-cut

edit-find

go-down

go-jump

go-next

go-previous

go-up

hg-annotate

hg-archive

hg-clone

hg-commit

hg-grep

hg-incoming

hg-log

hg-merge

hg-outgoing

hg-pull

hg-push

hg-qguard

hg-qpop-all

hg-qpop

hg-qpush-all

hg-qpush

hg-rename

hg-status

hg-tag

hg-update

mail-forward

process-stop

tasktab-refresh

thg-console

thg-log-load-all

thg-mq

thg-qreorder

thg-reporegistry

thg-sync

view-filter

view-refresh

さいごに

どうやって設定するんだろ、と1ヶ月もモヤモヤしてたのがスッキリしました。

よかったら参考にしてください。それでは。

2012-05-11

Koonies2012-05-11

TortoiseHgでAmendを使うと2つ前のコミットをやり直せる

TortoiseHgはバージョン管理ソフトMercurialWindowsフロントエンドで、つい先日にリリースされた最新版v2.4でAmendというコマンドが追加されました。Amendを使えば、お手軽に直前のコミットをやり直すことが可能になります。

以前のバージョンでもロールバックして、コミットし直せば同様のことが可能だった訳ですが、実際の操作手順としてはAmendを使った方がコミットのメッセージコピーする必要もないため地味に便利です。リリースされてからまだ数日ですが、既に何度もお世話になってます。

さてタイトルにも書いた「2つ前」の修正の話。

これまでは「1つ前」の修正ならロールバック、それ以上前の修正をやりたい場合はMQなどのエクステンションを使う必要がありました。

最新版では「1つ前」の修正ならロールバックまたはAmendのどちらでもOKになりました。という事はロールバックして、更にAmendすれば「2つ前」を修正できる??という疑問が湧いてきますよね。それで試してみたら、本当に出来ました

手順

1. まずはロールバック

2. 直前の変更点をシェルフ待避

3. コミットの画面にする

4. コミットボタンの隣の▼をクリックし、"Amend current revision"をクリック*1

5. するとボタン表示がコミット→Amendに変わり、「2つ前」のコミットメッセージが表示されるので、修正してAmendボタンをクリック

6. シェルフで待避した変更点を戻し、あとは普通にコミットをやり直す。

さいごに

Mercurialでも同様のことが出来そうな気がしますね。試してないけど。それでは。

*1:ただしAmendはMQエクステンションが有効でないと使用できないみたいなので注意!

2011-09-06

keyhacでCapsLockをモディファイアキー定義して無理矢理使う

keyhacの話。ある2chのスレを見ていたら、keyhacでCtrlとCapsLockキーを入れ替えようとしたが無理だった、というやりとりを見かけました。

CapsLockというキーは他のキーとは違いDownのイベントは発生するけど、Upは発生しない(ドライバマスクしているらしい)ため、Ctrlと入れ替えた場合、押されっぱなしの状態になるとか。

試しにkeyhacで内部ログON*1にして、CtrlとCapsキーを押してみると

# Ctrlを押して離した場合

IN  : D-LCtrl
TRU : D-LCtrl
IN  : U-LCtrl
TRU : U-LCtrl
IN  : O-LCtrl

# CapsLockを押して離した場合

IN  : D-(240)
TRU : D-(240)

という風にCapsLockは「U-(240)」が出力されていません。だから入れ替えは無理、か。確かにこれは無理だなと思う反面、出来ないと言われると、何とかしたくなるのが人情

で、色々考えた末、入れ替えは無理でもユーザー定義のモディファイアキー*2としてなら使えるかもと思い、書いてみました。

コード

# config.py

from keyhac import *


def configure(keymap):

    ## 関数実行時にモディファイアの状態をリセットするデコレータ
    def reset_modifier(func):
        import functools

        @functools.wraps(func)
        def _reset_modifier(*args, **kw):
            # モディファイアの状態を無理矢理リセット
            keymap.modifier = 0
            # 関数実行
            return func(*args, **kw)
        return _reset_modifier

    ## JobQueue/JobItem でサブスレッド処理にするデコレータ
    def job_queue(func):
        import functools

        @functools.wraps(func)
        def _job_queue(*args, **kw):

            num_items = JobQueue.defaultQueue().numItems()
            if num_items:   # 処理待ちアイテムがある場合は、その数を表示
                print u"JobQueue.defaultQueue().numItems() :", num_items

            def __job_queue_1(job_item):
                return func(*args, **kw)

            def __job_queue_2(job_item):
                # print "job_queue : ", func.__name__, args, kw
                pass

            job_item = JobItem(__job_queue_1, __job_queue_2)
            JobQueue.defaultQueue().enqueue(job_item)

        return _job_queue

    ## 一定時間経過後にモディファイアの状態をリセット
    @job_queue
    def auto_reset_modifier():
        import time
        WAIT_TIME = 0.5  # 秒
        time.sleep(WAIT_TIME)
        # モディファイアの状態を無理矢理リセット
        # if keymap.modifier: print keymap.modifier
        keymap.modifier = 0

    @reset_modifier
    def minimize():
        keymap.getTopLevelWindow().minimize()

    # どのウインドウにフォーカスがあっても効くキーマップ
    keymap_global = keymap.defineWindowKeymap()

    # ユーザモディファイアキーの定義:CapsLock(240) --> U1
    keymap.defineModifier("(240)", "U1")

    # 単体押しは一定時間後にモディファイアの状態をリセット
    # keymap_global["U1"] = auto_reset_modifier     # これだとキー表記エラー
    keymap_global["(240)"] = auto_reset_modifier

    # Caps + a : ウィンドウ最小化
    keymap_global["U1-a"] = minimize

関数定義で@reset_modifierのデコレータを使うと、関数の実行時にモディファイアキーの状態をリセットします。これによりCapsLockキーの押されっぱなしを防止しています。

これで一応モディファイアっぽく使えます。ただしタイトルに「無理矢理」と書いたように同時押しでなくても

CapsLockを押す → 離す → (0.5秒以内に)Aを押す

でも認識されてしまいます。また、CapsLockを押したままA、Aと2回押すと、2回目のAは同時押しではないAになってしまう等の欠点があります。

■ さいごに

日頃からCapsLockキーって押しやすい場所にあるのに全然使ってないなと思っている方はどうぞ。

■ 参考リンク

ページが見つかりませんでした - craftware

キーカスタマイズソフト 2

*1:トレイアイコン右クリック→内部ログONをクリック

*2:Ctrl・Shift・Alt・Winキーのような装飾キー

2011-08-28

keyhacでテキストエディタのF1キーに任意のヘルプファイルのキーワード表示に関連づける

またまたkeyhacでのカスタマイズネタ。テキストエディタでプログラムを書いていると、そのプログラム言語のヘルプファイルが見たいってことがしばしばあります。そんなときに役立つ設定です。

■ 使い方

使い方はカンタン。テキストエディタ上で調べたい単語を選択しF1を押します。

そうすれば設定しておいたchm形式のヘルプファイルからキーワード検索し、その項目を表示します。

コード

・ chm_viewer.py

まずは↓の部分をchm_viewer.pyという名前保存し、extensionフォルダに置いてください。

# chm_viewer.py
# http://d.hatena.ne.jp/pipehead/20071121/1195597559 のCraftLaunchEx用コードをほぼそのまま利用

# Windows 2000/XP では Unicode 版 (HtmlHelpW) を使用し、2000/XP 以外では ANSI 版 (HtmlHelpA) を使用します。
def _IsWinNT5OrLater():
    import sys

    (major, platform) = sys.getwindowsversion()[0:4:3]
    # VER_PLATFORM_WIN32_NT: 2
    return ((platform == 2) and (major >= 5))

winNT5OrLater = _IsWinNT5OrLater()


def _T(string):
    if isinstance(string, str):
        string = unicode(string, 'utf-8')
    if not winNT5OrLater:
        return string.encode('mbcs')
    return string


import ctypes

class c_tchar_p(ctypes._SimpleCData):
    if winNT5OrLater:
        _type_ = 'Z' # c_wchar_p
    else:
        _type_ = 'z' # c_char_p


# WinUser.h
GetDesktopWindow = ctypes.windll.user32.GetDesktopWindow


# HtmlHelp.h
HH_DISPLAY_TOC    = 0x0001
HH_KEYWORD_LOOKUP = 0x000D
HH_CLOSE_ALL      = 0x0012


from ctypes.wintypes import BOOL

class HH_AKLINK(ctypes.Structure):
    _fields_ = [
        ('cbStruct',     ctypes.c_int), # sizeof this structure
        ('fReserved',    BOOL),         # must be FALSE (really!)
        ('pszKeywords',  c_tchar_p),    # semi-colon separated keywords
        ('pszUrl',       c_tchar_p),    # URL to jump to if no keywords found (may be NULL)
        ('pszMsgText',   c_tchar_p),    # Message text to display in MessageBox if pszUrl is NULL and no keyword match
        ('pszMsgTitle',  c_tchar_p),    # Message text to display in MessageBox if pszUrl is NULL and no keyword match
        ('pszWindow',    c_tchar_p),    # Window to display URL in
        ('fIndexOnFail', BOOL)          # Displays index if keyword lookup fails.
    ]


if winNT5OrLater:
    HtmlHelp = ctypes.windll.LoadLibrary('hhctrl.ocx').HtmlHelpW
else:
    HtmlHelp = ctypes.windll.LoadLibrary('hhctrl.ocx').HtmlHelpA


def HtmlHelpDisplayTOC(chmPath, data=None):
    u"""指定されたヘルプウィンドウでヘルプトピックを開く

    引数  : chmPath - 文字列 - コンパイル済みヘルプまたはコンパイル済みヘルプ
            ファイル中のトピック
    引数  : data - 数値 - コンパイル済みヘルプファイル中のトピックへのポインタ
    戻り値: ヘルプウィンドウのハンドルを返す"""
    return HtmlHelp(GetDesktopWindow(), _T(chmPath), HH_DISPLAY_TOC, data)

def HtmlHelpKeywordLookup(chmPath, kwd):
    u"""コンパイル済みヘルプファイルからキーワードを検索する

    引数  : chmPath - 文字列 - コンパイル済みヘルプファイル
    引数  : kwd - 文字列 -  検索するキーワード
            複数の項目はセミコロン `;' で区切る
    戻り値: ヘルプウィンドウのハンドルを返す"""
    aklnk = HH_AKLINK(ctypes.sizeof(HH_AKLINK), False, _T(kwd), None, None,
                      None, None, True)
    return HtmlHelp(GetDesktopWindow(), _T(chmPath), HH_KEYWORD_LOOKUP,
                    ctypes.byref(aklnk))

def HtmlHelpCloseAll():
    u"""呼び出しプログラムによって開かれたヘルプウィンドウをすべて閉じる

    戻り値: なし"""
    HtmlHelp(None, None, HH_CLOSE_ALL, 0)
config.py

で、↓ がconfig.pyの設定部分で、キーの割り当てとヘルプファイルのパス設定などを行います。

下記の例ではメモ帳F1を押すとPythonのヘルプファイル(ダウンロードファイル一覧 - Python Japanese Environment - OSDN)を表示します。

# config.py

from keyhac import *

def configure(keymap):

    ## 選択文字列をヘルプファイル(*.chm)から検索
    def select_word_help():
        def _select_word_help():
            # ヘルプファイルのフルパス
            chm_path = r"C:\Program Files\craftware\keyhac\Python26-DocJa1.chm"

            before = getClipboardText()

            # 選択文字列をコピー
            copy_key = "C-c"
            keymap.command_InputKey(copy_key)()

            maxcnt = 10
            while maxcnt > 0:
                maxcnt -= 1

                # クリップボードから文字列取り込み
                select_word = getClipboardText()
                if select_word != before:
                    break

                # クリップボードの反映待ち
                import time
                time.sleep(0.1)

            if select_word:
                import chm_viewer
                chm_viewer.HtmlHelpKeywordLookup(chm_path, select_word)

            # クリップボードを元の状態に戻して終わり
            setClipboardText(before)

        # ホットキー経由での関数呼び出し
        keymap.callHotKey(_select_word_help)

    # メモ帳のキーマップ
    keymap_notepad = keymap.defineWindowKeymap(exe_name=u"notepad.exe")

    keymap_notepad["F1"] = select_word_help

■ さいごに

この前コードを書いていたら、ふとVisual Studioみたいに普段使いのエディタでもヘルプ表示ができたらいいのになァと思い立ち、ちょっと調べてみたら、ほぼそのまま流用可能なこちらのエントリを見つけたので、設定してみました。よければどうぞ。

■ 参考リンク

ページが見つかりませんでした - craftware

HTML ヘルプを表示する - anonymous苦労者

2011-08-19

keyhacでWindows7のエアロスナップをマネマネ。

DWindows7から導入されたエアロスナップ。要は画面左・右半分の最大化がマウス操作で簡単に実行できる機能です。ご存知ない方はこの30秒の動画を見てください。すごく便利な機能なんですが、僕の普段使いのPCXP。当然エアロスナップなんてありません。

だったらkeyhacの出番です。本家にない上半分・下半分も出来ちゃいます。ついでに移動、リサイズも紹介しときます。

コード

from keyhac import *

## 関数を返す関数にするデコレータ
def ret_func(func):
    import functools

    @functools.wraps(func)
    def _ret_func(*args, **kw):
        @functools.wraps(func)
        def __ret_func():
            return func(*args, **kw)
        return __ret_func
    return _ret_func

def configure(keymap):

    ## 10pixel単位のウインドウのリサイズ(最大最小のときは何もしない)
    #
    @ret_func
    def resize_window(direction):
        if not keymap.getTopLevelWindow().isMaximized():
            i = "LRUD".find(direction)
            dx, dy = ((-10, 0),  # L
                      (+10, 0),  # R
                      (0, -10),  # U
                      (0, +10)   # D
                     )[i]

            wnd = keymap.getTopLevelWindow()
            rect = list(wnd.getRect())
            rect[2] += dx
            rect[3] += dy
            wnd.setRect(rect)

    ## 10pixel単位のウインドウの移動(最大最小のときは何もしない)
    #
    @ret_func
    def move_window(direction):
        if not keymap.getTopLevelWindow().isMaximized():
            i = "LRUD".find(direction)
            dx, dy = ((-10, 0),  # L
                      (+10, 0),  # R
                      (0, -10),  # U
                      (0, +10)   # D
                     )[i]

            # keyhac_keymap.py 定義の関数を利用
            keymap.command_MoveWindow(dx, dy)()

    ## ウィンドウを画面端まで移動(最大最小のときは何もしない)
    #
    @ret_func
    def move_window_monitoredge(direction):
        if not keymap.getTopLevelWindow().isMaximized():
            i = "LURD".find(direction)
            # keyhac_keymap.py 定義の関数を利用
            keymap.command_MoveWindow_MonitorEdge(i)()

    ## 画面半分の切り替え(Windows7のエアロスナップ風)
    #
    @ret_func
    def toggle_aero_snap(direction):
        wnd = keymap.getTopLevelWindow()
        if wnd.isMaximized():
            # 元に戻す
            wnd.restore()
        else:
            # 最大化
            wnd.maximize()

            # ウィンドウのサイズを取得
            rect = list(wnd.getRect())

            # ウィンドウの幅/高さの半分
            width_50 = (rect[0] + rect[2]) / 2
            height50 = (rect[1] + rect[3]) / 2

            # 入力された方向に応じて対応する座標を幅/高さの半分で上書き
            i = "RDLU".find(direction)
            rect[i] = (width_50,  # R
                       height50,  # D
                       width_50,  # L
                       height50   # U
                      )[i]

            # ウィンドウの新しいサイズを反映
            wnd.setRect(rect)

    # どのウインドウにフォーカスがあっても効くキーマップ
    keymap_global = keymap.defineWindowKeymap()

    ## ウィンドウ移動系
    for arrow_key in ("Left", "Right", "Up", "Down"):
        c = arrow_key[:1]

        # Win+←→↑↓ : 10pixel単位のウインドウの移動
        keymap_global["W-" + arrow_key] = move_window(c)
        # Win+Ctrl+←→↑↓ : 画面の端まで移動
        keymap_global["W-C-" + arrow_key] = move_window_monitoredge(c)
        # Win+Shift+←→↑↓ : 10pixel単位のウインドウのリサイズ
        keymap_global["W-S-" + arrow_key] = resize_window(c)
        # Win+Alt+←→↑↓ : Windows7のエアロスナップ風
        keymap_global["W-A-" + arrow_key] = toggle_aero_snap(c)

■ 軽〜く説明

Win+←→↑↓10pixel単位ウインドウの移動
Win+Ctrl+←→↑↓画面の端まで移動
Win+Shift+←→↑↓10pixel単位のウインドウのリサイズ
Win+Alt+←→↑↓Windows7のエアロスナップ風

■ 参考リンク

2009 | 06 | 07 | 08 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 10 |
2011 | 01 | 02 | 05 | 06 | 07 | 08 | 09 |
2012 | 05 | 06 |
日記の検索

ads
最近のコメント
etc
あわせて読みたいブログパーツ