Hatena::ブログ(Diary)

=== SANDmark 19106 === beginning stress test このページをアンテナに追加 RSSフィード

2017年03月30日

続・OmegaT用: 正規表現のグループ参照を使って訳文を置き換えるスクリプトを書いたよ(GUI対応)


前回の記事からの続きです。

変更点

使い方

前提として、このスクリプト正規表現グループ参照を用いた置き換えを行うものです。通常の正規表現検索・置換はOmegaTのみで可能です。

regexp = /Sample segment named (.+) could be replaced with (.*)./
def replace(m) { "サンプル分節${m[1]}が${m[2]}に置き換えられます。" }

  • とある部分を変更し、検索に使う正規表現と置換後の文字列を設定します。
  • 『実行』をクリックするとプレビューウィンドウが出てきます。
  • メニュー -> 実行を選択すると、実際に置換を行います。

デフォルトでは

  • Sample segment named something could be replaced with RegExp.
  • Sample segment named whatever could be replaced with script.

上記パターンにマッチする分節すべてがそれぞれ

  • サンプル分節somethingがRegExpに置き換えられます。
  • サンプル分節whateverがscriptに置き換えられます。

と置換されます。

謝辞

OmegaTに含まれるGroovyスクリプトをおおいに参考にさせていただきました。感謝!

技術的な話

GUIなんてやるもんじゃない。
Groovy経由だからJavaほど構築が面倒なわけではないけど、やっぱりコード内でUIを定義しようとするとやっぱりすごいことになりました。長年見なかった感じのコードというか。ほとんどコピペなのでSwingなにそれな私でもなんとかなりました。いろんなサンプルを用意してくれるOmegaTプロジェクトに改めて感謝です。未だにimport staticの意味がわかってないけど許して。

ただ、他のスクリプトを見るとあんまりeachイテレータ使ってなくて、トラディショナルなforループが多いです。分節区切りを変更したらeachで拾えなくなる分節があったんですが、インデックスで参照してたら拾えてたのかな?

OmegaTスクリプトを書こうっていう人がどれくらいいるのかわかりませんが、書いてみると意外と簡単だったりします。現在のベータ版(4.1.1)ではシンタックスハイライトが実装されてたりするので、興味のある人は触ってみてくださいねー。

2017年03月29日

OmegaT用: 正規表現のグループ参照を使って訳文を置き換えるスクリプトを書いたよ


2017-03-30: 更新しました -> 続・OmegaT用: 正規表現のグループ参照を使って訳文を置き換えるスクリプトを書いたよ(GUI対応) - === SANDmark 19106 === beginning stress test

経緯と使い方

なんか前の記事から一年以上経ってて引きました。

最近は翻訳のお仕事をしているんですが、支援ツールとして翻訳メモリソフトOmegaTno title)を使ってます。Javaで書かれたオープンソースソフトウェアで、実はTRADOSの体験版ダウンロードしている最中に暇つぶしで触ってみたらそのまま実務用になってしまったという、脅威の機能性を持つあなどれないやつです。TRADOS体験版の試用期間はまだあるんだけど、多分触らないまま終わりそう。基本的な使い方はマニュアルが充実しているのでそっちに任せるとして、今回はややマニアックな需要です。

チャットログなんかを翻訳していると定型文が大量に引っかかるわけで、いくら参考訳文に出てきても200件あったら大変なわけですよ。もちろん置き換え機能はOmegaTにありますし、正規表現も使えるのだけど、これが "John talked to Jessie", "Jack talked to Jimmy" とか、そういうのが大量にあると単純には置き換えられない。

ので、スクリプトを書きました。ダウンロードしてOmegaTインストールディレクトリにあるscripts/にぶち込んでください。あとはOmegaTを起動してツール→スクリプト→regexp_replacement.groovy→実行です。コンソールにプレビューが表示されるので、キャンセルを繰り返しながら置き換え後の文章を確認しつつ、これだと思ったところで置き換えてください。操作は元に戻せないのでtmxファイルのバックアップを強く推奨します。自己責任でどうぞ。

Groovy自体はじめてだったのでいろいろ調べながらのわくわくさんクオリティでごめんなさい。自分でも相当使いづらいのでそのうち直します。

5行目が検索正規表現とグループ指定、6行目が置き換え後の文字列です。置き換え後の文字列がちょっと読みづらいですが仕様です。""でくくられた部分だけ編集しましょう。${m[1]}がひとつめの括弧、${m[2]}がふたつめの括弧…というように対応してます。

regexp = /(.*) talked to (.*)./
def replace(m) { "${m[1]}さんが${m[2]}さんに言いました。" }

/(.*) talked to (.*)./が例えば "(John) talked to (Jessie)" にヒットして、"JohnさんがJessieさんに言いました。" に置き換えられます。人名はがんばってください。

技術的な話

なんでハードコーディングしてるのかっていうと、OmegaTがグループマッチの部分参照に対応していないからです。どうもJavaのMatcherクラスが十分なメソッドを提供していないからっていう感じはしますが、Twitterでアドバイスをくれたエラリー・ジャンクリストフさんによると



とのことです。ひょっとすると将来的に実装されるかもしれませんが、現時点では他の機能のほうが需要が高い様子。まぁスクリプトでできたわけだしいいよね。

OmegaTはGroovyとJavaScriptの両方でスクリプトが書けますが、今回は好奇心もあってGroovyに挑戦しました。Rubyインスパイアされただけあってとりあえず書き下すのは楽でした。そのぶん処理の最適化とかまったくしていないコード(同じ処理を2回行う手抜き)なので、分節が10万とかになるとどうなるかわかりません。

置き換え後の文字列がStringじゃなくてクロージャになっているのは呼び出しの都合です。"_1さん_2さん"とかで参照したいんですが、面倒なので実装しません。

UIもハードコーディングでローカライズとかまったく考えてないんですが、よし海外ニーズがあったとしても、向こうにはもっといいものがあるでしょうきっと。

2013年08月14日

Papyrusログに MHP_ConfigQuest のスタックが溜まって落ちる人へ

私的経緯

例えば歩いているだけで錬金素材が集まるMODなんかを入れていると、
「持てるだけ持ち歩いて後でまとめて錬金しよう」とか思うわけです。
持ち歩ける重量が多ければ多いほど、のちのち「山の青い花 (280)」とかになる。
ちなみに私が愛用させてもらっているのはこちら。

当然300回近く R キーを押すなんて人間には至難の業で、
漏れそうな下を必死こいた気分で我慢しながら駅のトイレのドアを叩くような事態に陥るよりも、
きっとこういう連打ツールを使いたくなるはずなのです。

しかし使ってみるとわかるんですが、人智を超えたスピードでアイテムが作成されるため
Papyrusスクリプトエンジンには途方も無い負荷がかかります。
いや、本来は(多分)スクリプト関係ないんだけど、MODによってはあるようで。

MHP = More HotKeys Please

タイトルにある MHP_ConfigQuest は比較的有名かつ高機能なホットキーMODである*1

に含まれている MHP_PlayerScript.psc に含まれているものです。

上記ブログで言及されているように、More HotKeys Please(以下MHP)は
インベントリへのアイテムの追加、およびアイテムの削除をモニタリングしているので、
一度の錬金につき「一つ目の材料削除」「二つ目の材料削除」(オプション材料削除)「薬の追加」という
少なくとも合計3つ以上のイベントが同時に発生することになります。

原因はスクリプトの過負荷

さらにそのイベント内で深くネストされたIf - EndIfWhile - EndWhileブロックが大量にあって、
Papyrusコード的には結構な負荷がかかります。落ちても仕方がないレベルと言ってもいいです。
これはホットキーにポーション選択したときの<mag>を計算している――
つまり同じ名前の薬のうちどれを優先的に使用するかの判断をしているわけですが、
個人的に薬はSwiftPotionRebornを使っているのであんまり必要ありません。

ので、とにかく落ちないようにするためにスクリプトを書き換えてみました。
需要があればコンパイル済みの MHP_PlayerScript.pex もどこかに置きますが、
MHPの作者さんに申し訳が立たないので多分やりません。コードのみ。

スクリプトの書き換え準備

バージョンは More HotKeys Please v3.0 です。

必要なもの:

スクリプトのコンパイルに Creation Kit 本体は使いません。
くっついてくる Papyrus Compiler というものを使います。
\SteamApps\common\Skyrim\Papyrus Compilerに存在が確認できるはず。
無ければそこはプレイ用のSkyrimフォルダなので、Creation Kitインストールしたフォルダを漁りましょう。

発見できたら、デスクトップとか適当なところに簡単な .bat ファイルを作ります。
ドラッグ&ドロップでスクリプトをコンパイルしてくれる親切設計ですが、
CK をインストールしたフォルダとプレイ用 Skyrim フォルダを把握しておく必要があります。
が、今回は同一フォルダにインストールされているものとしましょうね。*2

compile_pupyrus.bat:

"D:\SteamLibrary\steamapps\common\skyrim\Papyrus compiler\PapyrusCompiler.exe" %1 -f="TESV_Papyrus_Flags.flg" -i="D:\SteamLibrary\steamapps\common\skyrim\data\scripts\source" -o="D:\SteamLibrary\steamapps\common\skyrim\Data\Scripts"
pause

D:ドライブの直下にSteamライブラリフォルダがあると仮定します。
場合によっては C:\Program Files(x86)\Steam\steamapps\... のようになっている可能性もあります。

PapyrusCompiler.exe は第一引数にスクリプトもしくはフォルダを取り、
-i にソーススクリプトの場所を指定、 -o にコンパイル済みスクリプトの出力先を指定するようです。
-f 引数についてはよくわかりませんが、あまり深く触らないほうが良さそうなのでおまじない。

スクリプトの改竄

MHP_PlayerScript.psc をどこか適当なところ(やはりデスクトップとか)にコピーし、適当なエディタで開きます。
このとき Data\Scripts\Source にあるものを直接編集してしまうとオリジナルが行方不明になるので、
確実にコピーを取るようにしてください。

それから次の行を探します。

  • Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
  • Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)

v3.0 では81行目、174行目にありました。
見付けたらそれぞれ2箇所編集します。 ; 記号から後ろはコメントとみなされて無視されますが、
日本語が入っているとコンパイルに失敗する可能性があるかもです。

まずは MHP_PlayerScript.psc: (OnItemAdded付近)

Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
	If akBaseItem.gettype() == 46
		If Writer.PotionEffects.length < 58
			Writer.PotionEffects = New MagicEffect[58]
			int i = 0
                        ; この下をいじくる
			; while i < Writer.PotionEffects.length ←コメントアウト
			while i < 0 ; 追加
				Writer.PotionEffects[i] = writer.MHP_AlchEffects.getat(i) as MagicEffect
				i += 1
			endwhile
		endif
		potion tempPotion = akBaseItem as Potion
		int count = tempPotion.getnumeffects()
		int j = 0
                ; この下もいじくる
		; while j < count ←コメントアウト
		while j < 0 ; 追加

それぞれ 0 を指定するとポーションの使用に支障をきたす可能性があるので、
必要に応じて数値を変更してください。具体的な目安はわかりませんが、5から10など。
数値が大きくなればなるほど負荷が大きくなります。
逆に 0 を指定した場合はループが一切回らなくなるので、負荷はほとんどかからなくなります。

続いて OnItemRemoved ですが、こちらも同じようなコードを2箇所変更します。
作用・副作用については上記と同じ。
MHP_PlayerScript.psc: (OnItemRemoved付近)

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
	If akBaseItem.gettype() == 46 && player.GetItemCount(akBaseItem) <= 0
		If Writer.PotionEffects.length < 58
			Writer.PotionEffects = New MagicEffect[58]
			int i = 0
                        ; この下をいじくる
			; while i < Writer.PotionEffects.length ←コメントアウト
			while i < 0 ; 追加
				Writer.PotionEffects[i] = writer.MHP_AlchEffects.getat(i) as MagicEffect
				i += 1
			endwhile
		endif
		potion tempPotion = akBaseItem as Potion
		int i = 0
                ; この下もいじくる
		; while i < Writer.KeyForm.length ←コメントアウト
		while i < 0 ; 追加

コンパイルと設置

あとはもうコンパイルするだけです。
といっても簡単で、先ほど改竄した MHP_PlayerScript.psc compile_pupyrus.bat にドラッグ&ドロップするだけ。
コンパイルに必要なファイルが自動的にロードされ、即座にコンパイルが始まります。

Starting 1 compile threads for 1 files...
Compiling "MHP_PlayerScript"...
Starting assembly of MHP_PlayerScript
0 error(s), 0 warning(s)
Assembly succeeded

Compilation succeeded.

Batch compile of 1 files finished. 1 succeeded, 0 failed.

こんな感じの文字が表示された黒いウィンドウが出るはずです。
もし Batch compile of 1 files finished. 0 succeeded, 1 failed. と表示されている場合は
コンパイルに失敗しているので、必要なファイルがあるかどうか確認してください。

SKSE, SkyUI のスクリプトのソースが展開されているかどうか、
compile_pupyrus.bat に記述されている -i= のフォルダが正しいかどうか、などです。
Batch compile of 1 files finished. 1 succeeded, 0 failed. と表示されていれば成功しているので、
何か適当なキーを押すか、右上の☓ボタンでウィンドウを閉じてしまって大丈夫です。

確認

さて実際にスクリプトが更新されたのかどうかですが、
Data\Scripts フォルダを開いて日付順に整列させればすぐに分かります。
直近に更新されたファイルが MHP_PlayerScript.pex になっていれば成功です。

もしそうでなければコンパイルに失敗しているか、
どこか別のところにスクリプトが出力されている可能性があります。
compile_pupyrus.bat-o= のフォルダを確認してみてください。

ゲームの起動

いつも通り起動してしまって問題ないはずです。
ただし動いているのは改竄済みのスクリプトなので、
ポーション関係、あるいはまったく別のところでおかしな動きをしても、自己責任ということで。

私への質問などは構いませんが、間違っても More HotKeys Please のフォーラムに
バグ報告などはしないようにしましょう。もっとも、私も MHP について
完全に把握しているわけではないので、これでいいのかどうかもまだわかりません。

ご利用は計画的に

*1:最初はGRHotkeys使ってたんだけどScriptDragonの導入が面倒になってやめてしまったよ…。

*2:なぜなら解説が面倒だから。

2012年11月22日

今更だけどrvmからrbenvに乗り換えるときの個人用メモ

ruby-2.0.0-devを使いたいのにrvmが対応してない。
というだけの理由で、rbenvに乗り換えることにしました。
rvmも便利だったのですが、cdコマンドを書き換えたりと
結構ブラックなこともやっていたので、いい機会かなと。
なんだか長くなっちゃったので省略されました。

rvmとrbenvの違い

  • rvmはビルドからgemsetまで面倒を見てくれる
  • でも結構多方面に影響するので怖い部分もある
  • rbenv「ビルドツールなんてありません」
  • rbenv「でも ruby-build っていうのがあるからそれ使ってもいいよ」
  • rbenv「gemはbundleで各自管理してください」

rbenvさんは結構放任主義みたいです。
※とっても語弊があるので詳細についてはGoogle先生にお尋ねください。

まずはrvmをアンインストール

する前に注意事項。
端末はひとつだけ開いた状態で作業すること。
そして言うまでもなくgemはすべて消し飛びます。
※私はこの大前提を忘れて混乱しました。
シェル:

$ rvm seppuku

切腹って。
いざ消そうとするときに限ってそういう……。
まぁいいや、とにかくこれで ~/.rvm が存在していないことを確認し、
それから .zshrc なりに書き加えた各種rvm用の関数などを手作業で削除。
これでおしまいです。
アンインストールが終わったら端末を再起動すること。
※私はこの大前提を(ry

rbenvのインストール

続いてこちらがrbenvになります。
が、Ubuntu12.10にはパッケージがあったのでそちらを使用。
シェル:

$ sudo apt-get install rbenv

今のところこれで問題なしです。

それから(私はzshを使っているので) ~/.zshenv に下記を追加。
~/.zshenv:

eval "$(rbenv init - zsh)"

bashを使っている方は zsh の部分を削り取れば行けるはずです。多分。

ruby-buildのインストール

ビルドツールとして ruby-build を使おうと思います。

こちらもUbuntuのパッケージにあったのですが、
rbenvのプラグインとして使ったほうが何かと都合が良さそうでした。*1

というわけでシェル:

$ mkdir -p ~/.rbenv/plugins/
$ git clone git://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build

これでいつでもパッケージリストを更新できるのでお手軽です。
さらに、環境変数で MAKEOPTS もしくは MAKE_OPTS を設定しておくと、
値を make コマンドの引数に渡してくれます。

例えば ~/.zshenv なんかに:

export MAKEOPTS="-j5"

とか書いておくと、CPUコアがたくさんある人は幸せになれます。

Ruby1.9.3-p327とRuby-2.0.0-devのインストール

前置きが長くなりましたがいよいよインストール。
シェル:

$ rbenv install -l                   # インストールできる処理系・バージョン一覧(ruby-buildに依存)
$ rbenv install 1.9.3-p327 --verbose # rvm と同じ感覚でインストールできる
$ rbenv install 2.0.0-dev  --verbose
$ rbenv global 1.9.3-p327            # 全体で使うruby処理系を指定
$ ruby -v
ruby 1.9.3p327 (2012-11-10 revision 37606) [i686-linux]

"ruby -v" の出力が違うよーっていう人は端末を再起動したらいいと思います。

gemの設定

rvmと違ってrbenvの場合、新しいgemをインストールするたびに

$ rbenv rehash

しなければならないという、自由への代償的なものがあります。
さすがに面倒くさいので何とかしたい。

というわけでこんな便利ツールが。
gemをインストール/アンインストールするたびに rbenv rehash を実行してくれる
痒いところに手が届く感じのgemです。
ついでに bundle もインストールしましょう。

シェル:

$ gem i rbenv-rehash
$ gem i bundle
$ bundle

これで bundle が実行できれば大丈夫です。多分。

その他

$ rbenv shell VERSION

とかやった時は手動で

$ rbenv rehash

しなきゃいけない……っぽい?

*1:パッケージリストがruby-buildで管理されているので。

2012年11月17日

Linux版ChromeにSmoothGesturesをインストール(ドラッグ&ドロップ)


結論から言うと、ChromeのバグのせいでLinux環境で使えるマウスジェスチャ拡張がほぼ無いのです。
どうも右クリックイベントをうまく取れないらしく、
ジェスチャーと同時に右クリックメニューが開いてしまう。

唯一まともに動作していたのが Smooth Gestures だったのですが、
これもChromeウェブストアから「マルウェア/スパイウェア」認定されて消滅。*1

ではLinux環境ではマウスジェスチャは絶望的なのか、と思って調べたところ、
有志の方が以下のサイトで『情報送信しない版』と『Linux用パッチ』を公開されてました。

しかし最近のChromeさんはとってもセキュリティに敏感で
ウェブストア以外からは拡張機能をインストールさせない
という制限を設けているため、そのままインストールというわけにはいきませんでした。

曰く「どうしてもインストールしたいなら『ツール→拡張機能』タブにファイルをドロップしろ」
とのことでしたが、すみませんChromeさんちょっといいですか、
Nautilusからドラッグしても反応してくれませんよね?

Webページにドラッグするとしっかり「インストールできません」と言うくせに
なぜ拡張機能画面ではドラッグ&ドロップイベントを認識してくれないのですか。
セキュリティ面でちょっと厳しすぎやしませんか(#^ω^)

というわけで解決策は Sidan kunde inte hittas | Framkalla dina fotominnen になりました。
幸い Ubuntu 12.10 では apt-get 一発で行けたのでご参考までに。

シェル:

$ sudo apt-get install dragbox
$ dragbox smooth-gestures-0.15.4.crx
$ dragbox smooth-gestures-plugin-0.8.crx

これで dragbox のウィンドウが現れるので、
ここからChromeの『拡張機能タブ』にドロップしてやると、
今度こそようやくインストールしてくれました。

smooth-gestures-0.15.4.crx 単体でも動作はするのですが、
右クリックメニューを出したいときに連打しなければならないなど
操作する上で地味にフラストレーションが溜まるので、
後者の smooth-gestures-plugin-0.8.crx を入れてやることで
Windows環境と同じ操作感を得ることができます。

Googleさん、早くバグ直して欲しいです……。
ついでに、GoogleIME(mozc)の辞書もLinuxで使えるようにしてください……。
ではまた!

*1:実際、何らかの情報を特定のサイトへ送信していたそうです。