複数のクリップボード履歴をとるソフト、ClipMenuのバージョン0.2.1をリリースしました。
主な変更点:
- 履歴クリアの際に起こる不具合を修正。
- メニュー内のアイコン表示の不具合を修正。
- ホットキーで起動した際に、正しい位置に表示されない問題を修正。
- アクション機能の動作対象OSを、暫定的にMac OS X v10.4.xに限定(Mac OS X v10.5環境において、表示に問題が生じたため)。
今回は不具合の修正のみです。問題解決にご協力頂いた、Hiroさん、Tomさん、tanemoriさん、Hedderikさん、ありがとうございました。
それから、CotEditorに倣って、ドキュメントにベータ版の注意書きを明記しました。まだ安定していなくて、すみません。
ダウンロードはこちらからです。
» ClipMenu
複数のクリップボード履歴をとるソフト、ClipMenuのバージョン0.2をリリースしました。
主な変更点:
- アクション機能を実装。
- 環境設定画面にツールバーを搭載。
- メニューに、数字キーのショートカットを追加。
- 履歴を全消去できる、メニュー項目を追加。
- 動作対象OSを、Mac OS X v10.4以上に変更。
ご不便をおかけしましたが、やっと履歴のクリアができるようになりました
履歴の個別削除は、アクションメニューから行えます。アクションメニューの表示は、対象の履歴上で Shift + クリック するか、 Shift + Enter キーを入力します。
このメニューの表示方法は、本当なら右クリックで行いたかったんですが、技術的な理由により、今の形になりました。解決方法が見つかり次第、対応したいと思っています。
初期状態で使用できるアクションは、
- Capitalize
- lowercase
- Title Case
- UPPERCASE
- プレーンテキストとしてペースト
- 削除
の、6つです。さらに、日本語を対象とした、2つのスクリプトも同梱しています。
- 半角英数字を全角に変換
- 全角英数字を半角に変換
アクションメニューへの追加や削除は、環境設定パネルで行ってください。「アクション」タブで、右側のアウトラインビューから、左側のアウトラインビューにドラッグ&ドロップできます。

また、JavaScriptを使えば、自由に文字列加工用のアクションを作ることができます。スクリプトの書き方は、『JavaScriptアクションの書き方』を参考にしてください。
もしかしたら、説明を読むより、実際にやってみた方が簡単かもしれません。上述の、lowercaseやUPPERCASEは、たったの一行ですから。
不具合を見つけたり、説明が分かりづらいところなどが有れば、指摘していただけると助かります。メールでも、こちらにコメントでもOKです。
ClipMenuはフリーウェア(無料)ですから、お気軽に試してみてください。
ダウンロードはこちらどうぞ
» ClipMenu
基本
ClipMenuでは、ユーザーの作成したアクションを使って、テキスト形式のクリップボード履歴に対する文字列処理を行うことができます。ユーザーアクションの実行には、スクリプト言語のJavaScriptを使用します。
ClipMenuのJavaScript実行エンジンには、WebKitに含まれるJavaScriptCoreを利用しています。JavaScriptの動作仕様は、Safariを参考にしてください。なお、ClipMenuでは基本的に、コアJavaScript部分のみを使用します。
設置
ユーザー作成のJavaScriptファイルは、以下のフォルダに設置します。このフォルダが存在しない場合は、Finderから新規に作成してください。
/Users/<ユーザ名>/ライブラリ/Application Support/ClipMenu/script/action
スクリプトファイルの拡張子は、”.js” になります。これ以外の拡張子を持ったファイルは、無視されます。
actionフォルダ以下に存在するフォルダは、アクションメニューのサブメニューとして機能します。同じ種類のスクリプトファイルは、フォルダにまとめておくと便利です。
スクリプトの書き方
[クリップボード文字列]
ClipMenuアプリケーションから渡されたクリップボード履歴の文字列は、clipText 変数に代入されています。この変数に対して関数を適用したり、メソッドを実行して文字列処理を行ってください。
例)アルファベットをすべて大文字に変える
clipText.toUpperCase();
[処理の終了]
必要な処理が済んだら、return 文で値を戻します。return 文に渡す式の戻り値は、文字列か数値になるようにしてください。
例)アルファベットをすべて大文字に変えて、クリップボードに送る
return clipText.toUpperCase();
この時、return 文に式を指定しないと、クリップボード履歴に対する処理は何も行われません。
例)何も返さず、終了
return;
[ライブラリの読み込み]
複数のファイルで共通して使用する関数などは、ライブラリとして別ファイルに保存しておくと便利です。ClipMenuでは、指定したフォルダに置かれたスクリプトを、ライブラリとして読み込むことができます。読み込みには、ClipMenuオブジェクトの、require() メソッドを使用します。
例)inflection-jsを読み込む
ClipMenu.require('inflection');
require() メソッドの引数には、ライブラリスクリプトのファイル名を渡します。拡張子の”.js”は、有っても無くても構いません。読み込みが成功したかどうかは、require() メソッドの戻り値を使ってチェックできます。ライブラリが見つかれば 1 を、見つからなければ 0 を返します。
例)require() メソッドの戻り値をチェック
var isExist = ClipMenu.require('inflection');
if (!isExist) {
throw new Error('Cound not find the file');
}
ライブラリの読み込みが成功すると、ライブラリ内で定義された関数が利用可能になります。
例)inflection-jsで定義された、capitalize() メソッドを使用する
clipText.capitalize();
ライブラリフォルダには、アプリケーションバンドル内にある標準ライブラリフォルダと、ユーザーが設置するユーザーライブラリフォルダの二種類があります。ユーザーライブラリフォルダは、以下のパスに作成してください。
/Users/<ユーザ名>/ライブラリ/Application Support/ClipMenu/script/lib
ライブラリの読み込みは、ユーザーライブラリフォルダが優先されます。こちらから検索した後、標準ライブラリフォルダの検索を行います。
[ユーザー入力]
prompt() メソッドを使用すれば、ユーザー入力を組み合わせた処理ができます。
例)クリップボードにコピーしたURLと、入力したタイトルを組み合わせて、HTMLコードを作成
var input = prompt('タイトルを入力:');
return '<a href="' + clipText + '" title="' + input + '">' + input + '</a>';
その他
- alert() 、 confirm() メソッドは動作しません。
次のような動作を、ClipMenuで実現しようと思いました。
- ブラウザでURL (例: http://www.apple.com/)をクリップボードにコピー。
- エディタを起動。
- ClipMenuを呼び出して、さっきコピーしたURLを履歴から選び、JavaScriptで記述したアクションを実行。
- JavaScript内に書かれた、prompt()メソッドで表示されたダイアローグボックスに、タイトル (例: アップル)を入力。
- エディタに、JavaScriptで処理した結果 (例: <a href=”http://www.apple.com/” title=”アップル”>アップル</a>)をペースト。
JavaScript内に、prompt()などの、ウィンドウを表示させるメソッドを使わなければ、特に問題はありませんでした。ただ、クリップボードの文字列と、ユーザー入力の文字列を組み合わせた文字列処理を行いたかったので、いくつかの問題を解決する必要がありました。
最前面に、エディタのウィンドウが表示されている状態で、バックグラウンド専用(LSUIElement = 1)で動いているClipMenuからウィンドウを開くと、最前面にあったエディタのウィンドウの下に表示されてしまいます。
これを避けるために、Cocoaでは以下のメソッドを実行すれば、自分のウィンドウを最前面にすることができました。
[NSApp activateIgnoringOtherApps:YES];
ただ、この後にClipMenuが表示したウィンドウを閉じると、はじめに最前面にあったエディタのウィンドウが一番手前になりますが、フォーカスはあたっていません。そのため、このウィンドウにペーストすることができない状態になってしまいます。
ClipMenuが最前面になる前に、
- 最前面のウィンドウのIDを記憶
- ClipMenuを最前面に切り替え
- ClipMenuのウィンドウを閉じる
- さっき記憶したIDのウィンドウを最前面に切り替え
を行えば良さそうだと考えましたが、方法が分かりません。唯一思い浮かんだのは、AppleScriptを使ったものです。ただ、「AppleScriptで解決するのは最後の手段」と、メーリングリストで言っていた人もいたので、やはり他の方法を探すことに。
Xcodeのドキュメントで見当たらなかったため、例によって、Cocoabuilderで検索。見つかった方法は、Carbonの関数を利用するものでした。
» Cocoabuilder - (Edison Thomaz) Bring app to foreground in 10.5
ClipMenuを表示する直前に、GetFrontProcess()関数で記憶したProcessSerialNumberを、ClipMenuを閉じる際に、SetFrontProcess()関数で最前面に設定することで、望み通りの動作をさせることができました。
結構、Carbon APIを使わないと実現できない処理がありますね。
JavaScriptを使って、クリップボード履歴にある文字列を加工するテストがうまくいったので、環境設定パネルに、使用するマクロを選択できるインターフェイスを作成することにしました。
まず考えた方法が、チェックボックスの付いたリスト表示。Gmailなどでも使われていますね。チェックボックスを個別にチェックしたり、「すべてを選択」や「選択を解除」で、まとめてオン/オフすることもできます。
ただ、チェックボックスを連続してチェックしていくような単純作業は、数が多くなると苦痛なものです。見た目も、ちょっと野暮ったいですね。
次に考えたのが、TableView。NSTableViewは使ったこともあるし、二つのTableView間でドラッグ&ドロップすれば、チェックボックスも不要になります。
難点は、階層表示ができないこと。表示するマクロの数が少なければ問題ありませんが、そうでない場合に、一階層で多くのファイルを表示するのは見づらく感じます。
最終的には、OutlineViewを採用することになりました。これなら、階層表示ができますし、それをそのままメニュー内のフォルダとして利用することもできるからです。
ただ、これが思いの外大変で、予定よりずいぶん時間がかかる作業になってしまいました。
『Cocoa Programming』と「Theocacao: NSTreeController and Drag and Drop」を参考に始めて見たものの、なかなか思うような結果になりません。だいたい、ダミーのコードを使ったハックが必要だったり、非公開クラスの_NSArrayControllerTreeNodeを使用しないと、目的を達成できないというのも、何か変な気がします。Leopardでは改善されたようですが、Tigerでは結局中途半端な実装のままですし。
何とか望みの結果を達成できたのは、CocoabuilderのMLアーカイブのおかげです。
あと助かったのが、こちらの書き込み。
- NSOutlineView/NSTreeControllerのサンプル読み…難航中 | hippos-lab::blog
- NSOutlineView/NSTreeControllerのサンプル読み-2 | hippos-lab::blog
Appleの公開している、OutlineViewを使ったサンプルコード、SourceView。必要環境が”Xcode 3.0, Mac OS X 10.5″なので中身を見てなかったんですが、こちらのブログのエントリーを拝見してダウンロードしてみたところ、一部はTigerにも流用できることが分かりました。
初めは、Nodeクラスをつくる参考にしようと、BaseNodeを写経していたんですが、数カ所直してみたらTigerでもビルド可能なことが判明。Objective-C 2.0で採用された、”in”とNSIntegerを、NSEnumeratorやintに書き換えれば動くようになりました。
OutlineViewのセルにアイコンを表示することも、Leopardで採用された機能を使った、セパレータの表示以外は、TigerでもOKでした。どうして、アイコン画像をBaseNodeクラスが保持しているのか分からなかったので、変更を加えたりしたところもありましたが、基本的にはこのサンプル通りでうまくいきました。
これだけ手間取ると分かっていれば、こちらを後回しにして、リクエストのあった機能を実現させた方が良かった気もしますが、OutlineViewは他にも使い道があるので、これで良かったことにしておきます。定型文の管理インターフェイスも、これを使えそうです。
有用な情報を公開してくださっている方達に感謝です。
Recent Comments