keyhacでクリップボード内のJavaScriptコードを整形/圧縮(JSBeautifier/SlimIt)
JavaScriptをさわってる人ならご存知の人も結構いそうなOnline JavaScript beautifier。JavaScriptコードを見やすく整形してくれるWebサービスです。
僕はブックマークレットを作る際など便利でよく使っているのですが、サイトを見てるとコマンドラインバージョンということでPythonコードでも公開されていました。探したらSlimItという圧縮する方も発見。
keyhac*1でクリップボード内のテキストに対して直接実行できたら便利だろうなと書いたのが ↓ のコード。
Win+Jで整形、Win+Sift+Jで高圧縮、Win+Ctrl+Jで低圧縮、というキー配置にしています。
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 ## 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 ## JavaScriptコードを整形 # JSBeautifier : http://jsbeautifier.org/ @job_queue def jsbeautifier(): import jsbeautifier clipboard_text = getClipboardText() if clipboard_text: js_options = jsbeautifier.default_options() js_options.jslint_happy = True new_code = jsbeautifier.beautify(clipboard_text, js_options) setClipboardText(new_code) print print "/* jsbeautifier */" print "// before --------------------" print clipboard_text print "// after --------------------" print new_code ## JavaScriptコードを圧縮 # SlimIt : http://slimit.org/ # PLY : http://www.dabeaz.com/ply/ @ret_func @job_queue def jsminify(mangle=False): import slimit clipboard_text = getClipboardText() if clipboard_text: new_code = slimit.minify(clipboard_text, mangle) setClipboardText(new_code) print print "/* SlimIt (mangle=%s) */" % mangle print "// before --------------------", len(clipboard_text), "byte" print clipboard_text print "// after --------------------", len(new_code), "byte" print new_code def configure(keymap): keymap_global = keymap.defineWindowKeymap() # JavaScriptコードを整形 keymap_global["W-j"] = jsbeautifier # JavaScriptコードを圧縮(高圧縮) keymap_global["W-S-j"] = jsminify(mangle=True) # JavaScriptコードを圧縮(低圧縮) keymap_global["W-C-j"] = jsminify(mangle=False)
■ ライブラリのインストール
・JSBeautifier
https://github.com/einars/js-beautify/raw/master/python/jsbeautifier.py
↑ のファイルをkeyhacのextensionフォルダへコピーする。
・SlimItとPLY(コード解析)
https://github.com/rspivak/slimit
圧縮ファイルをダウンロードし、圧縮ファイルのsrcフォルダ下にslimitをフォルダごとkeyhacのextensionフォルダへコピーする。
http://www.dabeaz.com/ply/
圧縮ファイルをダウンロードし、圧縮ファイルのplyをフォルダごとkeyhacのextensionフォルダへコピーする。
■ さいごに
ブックマークレットをよく書くという方は特に便利だと思うので、よかったら使ってみてください。
■ 参考リンク
*1:Autohotkeyみたいなフリーソフトで、Pythonコードで色んなソフトのショートカットキーを設定できる
keyhacのPythonスクリプトにも便利なデコレータ
引き続き、keyhacネタ。keyhacはPythonでスクリプト(設定ファイル)を記述するのでもちろんデコレータも使えます。デコレータの説明はdecorator.htmlが分かりやすかったので、こちらを見ていただくとして早速コードの紹介。
■ 処理時間計測
上記のサイトで紹介されていたのをちょこっといじったのが、最初に紹介する処理時間計測をするデコレータ。
・デコレータ
from keyhac import * ## 処理時間計測のデコレータ def profile(func): import functools @functools.wraps(func) def _profile(*args, **kw): import time timer = time.clock t0 = timer() ret = func(*args, **kw) print '%s: %.3f [ms] elapsed' % (func.__name__, 1000 * (timer() - t0)) return ret return _profile
↑ をconfig.pyの先頭で定義しておく。そして、以下のように測りたい関数の直前に@profileを挿入する。
・使用サンプル
def configure(keymap): ## メモ帳を起動 @profile def exe_notepad(): shellExecute( None, None, "notepad.exe", u"", u"" ) keymap_global = keymap.defineWindowKeymap() keymap_global["W-n"] = exe_notepad
するとこの関数が実行されたとき(=Win+Nが押されたとき)にkeyhacのコンソール画面に以下のような情報が出力されるという仕掛け。
exe_notepad: 352.611 [ms] elapsed
新しく関数を追加するときなどに、こうした方が処理は速くなるかな?ってときにお手軽に時間計測できます。機能は地味だけどとても便利。
■ サブスレッド処理
つぎはサブスレッド化ってやつを簡単にするデコレータ。処理に時間がかかる関数は、サブスレッド処理で実行することが推奨されているようです。
・デコレータ
from keyhac import * ## 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を付ける)
@job_queue def exe_notepad(): shellExecute( None, None, "notepad.exe", u"", u"" )
もし ↑ をデコレータ使わずに書いたら ↓ になる。
def exe_notepad(): def _exe_notepad_1(job_item): shellExecute( None, None, "notepad.exe", u"", u"" ) def _exe_notepad_2(job_item): pass job_item = JobItem(_exe_notepad_1, _exe_notepad_2) JobQueue.defaultQueue().enqueue(job_item)
1つ2つなら良いが、毎回この処理を書くのが面倒になってきて、デコレータを使うようにしたらすごく楽チンになった。
■ キー定義
3つ目はキー定義。このキーが押されたらこの関数の実行するというのを関数定義と一緒に行う。
・デコレータ
from keyhac import * ## キー定義用デコレータ def def_key(window_keymap, key): def _def_key(func): window_keymap[key] = func return _def_key
・使用サンプル
このデコレータは、@def_key(ウィンドウキーマップ, キー表記文字列) という風に使う。
def configure(keymap): keymap_global = keymap.defineWindowKeymap() ## メモ帳を起動 @def_key(keymap_global, "W-n") # Win + N def exe_notepad(): shellExecute( None, None, "notepad.exe", u"", u"" )
これは以下のコードと同等になる。
def configure(keymap): ## メモ帳を起動 def exe_notepad(): shellExecute( None, None, "notepad.exe", u"", u"" ) keymap_global = keymap.defineWindowKeymap() keymap_global["W-n"] = exe_notepad # Win + N
このデコレータではコード記述量は減らないが、関数定義とキーへの紐付けを同時にできるのでコードがシンプルで分かりやすくなる。
■ 関数を返す
4つ目は関数を返す関数にするデコレータ。引数をともなう関数をキー割り当てするときには、関数を返す関数にする必要がある。それが面倒になって作ったのがこのデコレータ。
・デコレータ
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
・使用サンプル
関数定義の前に@ret_funcを挿入する。
def configure(keymap): # 引数のパスを起動する @ret_func def exe_sub(path): shellExecute( None, None, path, u"", u"" ) keymap_global = keymap.defineWindowKeymap() keymap_global["W-n"] = exe_sub("notepad.exe")
これは以下のコードと同等になる。
def configure(keymap): # 引数のパスを起動する(デコレータ無し版) def exe_sub(path): def _exe_sub(): shellExecute( None, None, path, u"", u"" ) return _exe_sub keymap_global = keymap.defineWindowKeymap() keymap_global["W-n"] = exe_sub("notepad.exe")
■ さいごに
とりあえずこんなところで。デコレータおもしろい。というかPythonおもしろいです。また何かあったら追加しときます。
追記(2011.08.02)
■ キー定義(別パターン)
3つ目のキー定義の亜種。このサイトの@addtoを使ってwindow_keymapを呼び出し可能にしてしまう。上で書いたやつよりシンプルでいいかもしれない。
・デコレータ
from keyhac import * # http://wiki.python.org/moin/PythonDecoratorLibrary#Easy_adding_methods_to_a_class_instance def addto(instance): def decorator(f): import types f = types.MethodType(f, instance, instance.__class__) setattr(instance, f.func_name, f) return f return decorator def configure(keymap): def define_window_keymap(*args, **kw): window_keymap = keymap.defineWindowKeymap(*args, **kw) print args, kw @addto(window_keymap) def __call__(self, key): def def_key(func): self[key] = func return def_key return window_keymap
・使用サンプル
# keymap.defineWindowKeymap の代わりに define_window_keymap を使う keymap_global = define_window_keymap() # 通常どおりのキー設定も可能 keymap_global["S-C-w"] = "LWin" # デコレータにもなる @keymap_global("W-n") def exe_notepad(): shellExecute( None, None, "notepad.exe", u"", u"" )
■ 参考リンク
keyhacからcomtypes経由でExcelマクロ関数をコールする
前回に引き続き、keyhacネタ。keyhacはPythonコードでWindowsのショートカットキーをカスタマイズできるフリーソフト。バージョン1.34からcomtypesが使用できるようになった。
このおかげでWScriptでやれていたことがkeyhacでもできるようになった。下記コードのようにすればExcel側で定義している自作マクロ関数も呼び出せる。
from keyhac import * def configure(keymap): def personal_xls(macro_name, *args): def _job_1(job_item): import comtypes.client xl = comtypes.client.GetActiveObject("Excel.Application") is_older_than_2007 = lambda: float(xl.Version) < 12 if is_older_than_2007(): book_name = "PERSONAL.XLS" else: book_name = "PERSONAL.XLSB" xl.Run(book_name + "!" + macro_name, *args) def _job_2(job_item): # print macro_name, args pass job_item = JobItem(_job_1, _job_2) JobQueue.defaultQueue().enqueue(job_item) # Excel用キーマップ keymap_excel = keymap.defineWindowKeymap(exe_name=u"EXCEL.EXE") # ボタンを大きくするマクロ keymap_excel["C-S-b"] = lambda: personal_xls("SwitchLargeButtons") # 引数付きの関数もコール可能! keymap_excel["C-S-m"] = lambda: personal_xls("Macro1", u"abcde.") keymap_excel["C-S-n"] = lambda: personal_xls("Macro1", u"あいうえお!")
一応Excel2003も2007も動くようにしている。
それとSwitchLargeButtonsは前に書いたやつ → 一発でエクセルのボタンをビッグサイズに切り替えるマクロ
ちなみにこのコードではJobQueueを使っているが、これを使わずに直に関数コールするとエラーにになってしまう。
ERROR : _onKeyDown failed [Error -2147417843] アプリケーションが入力同期呼び出しをディスパッチしているため、呼び出せません。 Traceback (most recent call last): File "keyhac_keymap.pyo", line 804, in _onKeyDown File "keyhac_keymap.pyo", line 728, in _keyAction File "C:\Program Files\craftware\keyhac\config.py", line 1764, in <lambda> File "C:\Program Files\craftware\keyhac\config.py", line 1747, in personal_xls File "comtypes\client\__init__.pyo", line 180, in GetActiveObject File "comtypes\__init__.pyo", line 1165, in GetActiveObject File "_ctypes/callproc.c", line 936, in GetResult WindowsError: [Error -2147417843] アプリケーションが入力同期呼び出しをディスパッチしているため、呼び出せません。
Excelは無理なのかなと色々試してたら一応動いた。結果オーライ。ますますkeyhacが便利になったなー。
■ 参考リンク
PCで音楽再生中に一時停止し、ちょっとしたら自動再開させる方法
ゴールデンウィークあたりからkeyhacというソフトでのカスタマイズにハマっています。
これで何ができるかというと、ソフトの名前(キーハック)のとおりいろんなソフトのショートカットキーをハックできてしまうのです。
ショートカットキーといえばCtrl+CのコピーとかCtrl+Vの貼り付けが有名どころですが、これらのキーと同じようなやつをユーザー側で定義して、勝手にショートカットキーを後付けしてしまおうというソフトな訳です。
で、その定義方法はLL言語のPythonで記述するようになっています。これが良い。すごく良い。
Pythonはまだ始めたばかり(条件文や関数のあとの:をしょっちゅう忘れるくらい)ですが、基本的にシンプルな言語なので書いてて楽しい。この処理よく使うな、よし定義だ、みたいな。
で、前置きが長くなったんですが、「Windows Media Playerとかで音楽再生中に一時停止し、5分したら自動再開させる」という「Alt+Shift+P」で実行させるためのスクリプト。
from keyhac import * def configure(keymap): def music_pause_and_play(): def job_music_pause_and_play(job_item): import time keymap.command_InputKey("(%d)" % VK_MEDIA_PLAY_PAUSE)() time.sleep(5 * 60) # [sec] keymap.command_InputKey("(%d)" % VK_MEDIA_PLAY_PAUSE)() job_item = JobItem(job_music_pause_and_play) JobQueue.defaultQueue().enqueue(job_item) keymap_global = keymap.defineWindowKeymap() keymap_global["Alt-Shift-P"] = music_pause_and_play
ちなみに
keymap.command_InputKey("(%d)" % VK_MEDIA_PLAY_PAUSE)()
の部分は、以下のように書き換えても同様に動作します。(多分 ↓ こっちの方が処理は軽い)
pyauto.Input.send([pyauto.Key(VK_MEDIA_PLAY_PAUSE)])
なお、上記のスクリプトは、『別の作業をして音楽を一時停止させた後、再生し忘れる人は必見のスクリプト | ライフハッカー[日本版]』でAutoHotkey*1を使った方法として紹介されていてナルホドな〜、と思ったのでkeyhacでもやってみました。
PCで音楽を聴いているところに電話がかかってきたときに便利ですね。
(とっさにAlt+Shift+Pは個人的にはちょっと押しにくい気もするけど)
そんな訳でkeyhacおすすめです。WindowsユーザーでPythonに興味のある方は是非。また何か思いついたら書きたいと思います。
*1:keyhacと同様のショートカットキー定義ソフト、こっちの方が有名だが独自言語に馴染めなかった
超便利なChrome拡張のSmooth Gesturesのカスタムアクション設定方法
Google Chromeの拡張機能であるSmooth Gestures。たぶん定番拡張だと思うのですが、カスタムアクション(bookmarkletでの機能追加)の設定方法について検索してみたのですが、公式のヘルプも無いし解説ページも見つからなかったので自力でなんとかしてみました。
以下そのメモです。
・設定方法
■ オプションを開く
[+カスタムアクションを追加]のボタンを押す
■ javascriptでコードを書く&その他設定
ブロックが追加されるので、各項目を設定します。とりあえず手始めに「選択文字列でGoogle検索」です。
1.「starting anywhere」を「有効な選択がされているときのみ」に変更
2.アクションの名前として「Google 検索」を入力
3.アクションの説明として「選択文字列で検索」を入力
4.javascriptのコードを入力 ↓
(function(url){ window.open(url.replace("%s",encodeURIComponent(window.getSelection()))); })("http://www.google.co.jp/search?q=%s&num=100")
5:[save]ボタンを押す
・検索結果を背面のタブで開く場合は
それと上記のスクリプトだとアクション後に前面のタブで開くのですが、バックグラウンドのタブで開きたい場合は以下のようにすれば良いみたいです。
(function(url){ var a=document.createElement("a"); a.href=url.replace("%s",encodeURIComponent(window.getSelection())); var event=document.createEvent("MouseEvents"); event.initMouseEvent("click",true,true,window,0,0,0,0,0,false,false,false,false,1,null); a.dispatchEvent(event); })("http://www.google.co.jp/search?q=%s&num=100")
・他の検索も登録
ちなみに↓の★の部分を変更すれば、色々な検索エンジンも使えます。
(背面タブバージョンも同様です)
(function(url){ window.open(url.replace("%s",encodeURIComponent(window.getSelection()))); })("★")
↑ の★を ↓ のURLに置き換える
検索エンジン URL ■ amazon.co.jp ■ amazon.de(ボードゲーム:amazon販売のみに限定) ■ play:game (ボードゲーム)
■ はてなブックマーク ■ はてなブックマーク (タグで検索)
■ 英辞郎 ■ クックパッド ■ twitter検索 ■ 価格.com (注意*1) ■ -
これ以外にもChromeの検索エンジン設定(chrome://settings/searchEngines)からURLを持ってくれば大体イケると思います。
・リンク上で開始するアクションの設定例
1.「starting anywhere」を「有効なリンクのみ」に変更
2.アクションの名前として「Twitter 検索」を入力
3.アクションの説明として「リンクを検索」を入力
4.javascriptのコードを入力 ↓
(function(url){ window.open(url.replace("%s",encodeURIComponent(b.targets[0].href))); })("http://search.twitter.com/search?q=%s")
リンク先のページについてTwitterでの評判が見られます。
ちなみにこれも最後のURL部分を他に変えることで流用が可能です。
・画像上で開始するアクションの設定例
1.「starting anywhere」を「有効な画像のみ」に変更
2.アクションの名前として「TinEye(類似画像検索)」を入力
3.アクションの説明として「画像を検索」を入力
4.javascriptのコードを入力 ↓
(function(url){ window.open(url.replace("%s",encodeURIComponent(b.targets[0].src))); })("http://tineye.com/search?pluginver=bookmark_1.0&url=%s")
・さいごに
前は別のマウスジェスチャの拡張を使っていましたが、思い切って乗換えてみました。まだ使い始めてから日が浅いので↑のコードも何か不具合があるかもしれませんが、いまのところは良い感じです。よければご参考に。
Notepad++のNppExecの出力からタグジャンプする設定方法
検索結果の「Amazon.co.jpが販売」以外半透明化のgreasemonkey&bookmarklet
最近のAmazonに多いぼったくりや転売屋に引っかからないための検索フィルター(greasemonkeyスクリプト/bookmarklet)を作ってみました。
まずは次のスクリーンショットを見ていただくのが早いと思います。発売間近のニンテンドー3DSで検索したときの画面です。
■ビフォー
■インストール
好みでお好きな方をどうぞ!
★ greasemonkeyスクリプト版( ↓ のリンクをクリック)
★ ブックマークレット版( ↓ のリンクをブックマーク)
いまのところIEは非対応です。Google Chrome、Firefox、Operaでは動作確認OK、AutoPagerize・AutoPatchWorkにも対応しています。
おまけ
こっちも最近つくったAmazon系bookmarkletです。Amazonの商品ページで実行すると、そのカテゴリの売れ筋を表示します。
おわりに
何か不具合があればコメント等でご連絡ください。
結構便利だと思うのでよければどうぞ。
関連記事
激安!Amazonで初回限定版のDVD付きCDを買うとお得な理由(わけ)
「普通のAmazon」を「ダイナミックなAmazon」にするchrome拡張 AmazonImageSizeChanger
超簡単Amazonアソシエイトリンク生成greasemonkeyの「AmaGrea」
Amazonのぼったくり業者にはご注意!のgreasemonkey
Amazonで詳細を見る by AmaGrea |