Opera 15のショートカットキーカスタマイズ

/Applications/Opera.app/Contents/Versions/15.0.1147.132/Opera Framework.framework/Resources/opera.pakにデフォルト設定のJSONが入っていたので、これを参考にProfileディレクトリのPreferencesを書き換えれば色々できそう。 nストロークキーをマッピングできるかどうかは不明。 あとActionの連結ができればこれはもう最強伝説だね!

まあどうせまたLinux版は1年以上放置されそうだけど……。

"Keybindings": {
  "Settings": { "AdvancedEnabled": false },
  "Basic": {
    "AccessKeyToggle": ["Esc+Shift"],
    "AddBlankTab": ["Ctrl+T","Command+T"],
    "AddToBookmarks": ["Command+Shift+D","Command+D"],
    "Back": ["Command+Left"],
    "Bookmarks": ["Command+Shift+B", "Command+B"],
    "CloseActiveTab": ["Command+W", "Ctrl+F4"],
    "ClosePrivateWindow": ["Ctrl+Shift+Q"],
    "CloseWindow": ["Command+Shift+W"],
    "Copy": ["Command+C"],
    "Cut": ["Command+X"],
    "CycleBackwardInActivationList": ["Ctrl+F2"],
    "CycleForwardInActivationList": ["Ctrl+F1"],
    "Delete": ["Del"],
    "DevTools": ["Command+Alt+I"],
    "DevToolsConsole": ["Command+Alt+J"],
    "DevToolsInspect": ["Command+Alt+C"],
    "EditProperties" : ["Command+i"],
    "ErrorConsole": ["Command+Shift+O"],
    "Exit": ["Command+Q"],
    "Extension": ["Command+Shift+E"],
    "Find": ["Command+F"],
    "FindInline": ["OemPeriod","OemComma"],
    "FindNext": ["Command+G"],
    "FindPrevious": ["Command+Shift+G"],
    "FitToWidth" : ["F11+Ctrl"],
    "FocusAddressbar" : ["Command+L","Command+E","Ctrl+F5"],
    "FocusNextWidget": ["Tab"],
    "FocusPage" : ["Ctrl+F6"],
    "ForceReload": ["Shift+F5","Command+Alt+R"],
    "Forward": ["Shift+Backspace","Alt+Right","Command+Right"],
    "GoToEnd": ["End","Ctrl+End"],
    "GoToPage" : ["F2"],
    "GoToSpeedDial_1" : ["Command+1"],
    "GoToSpeedDial_2" : ["Command+2"],
    "GoToSpeedDial_3" : ["Command+3"],
    "GoToSpeedDial_4" : ["Command+4"],
    "GoToSpeedDial_5" : ["Command+5"],
    "GoToSpeedDial_6" : ["Command+6"],
    "GoToSpeedDial_7" : ["Command+7"],
    "GoToSpeedDial_8" : ["Command+8"],
    "GoToSpeedDial_9" : ["Command+9"],
    "GoToTop": ["Home","Ctrl+Home"],
    "HideOpera": ["Command+H"],
    "History": ["Command+Shift+H", "Command+Alt+2"],
    "Homepage" : ["Space+Meta", "Command+Home"],
    "NavigateDown": ["Down"],
    "NavigateLeft": ["Left"],
    "NavigateRight": ["Right"],
    "NavigateUp": ["Up"],
    "NavStop": ["Esc"],
    "OpenDocument" : ["Command+O"],
    "OpenLinkInBackground": ["Command+Shift+Enter"],
    "OpenLinkInNewPage": ["Command+Enter"],
    "OpenMenu" : ["Command+M"],
    "OpenPrivateWindow": ["Command+Shift+N"],
    "OpenWindow": ["Command+N"],
    "PageDown" : ["PageDown","Space"],
    "PageLeft" : ["Command+PageUp"],
    "PageRight" : ["Command+PageDown"],
    "PageUp" : ["PageUp"],
    "ParentDirectory": ["Command+Backspace"],
    "Paste": ["Command+V","Meta+Y"],
    "PasteAndGo": ["Command+Shift+V"],
    "PastePassword": ["Command+Alt+Enter"],
    "Preferences": ["Command+OemComma"],
    "Print" : ["Command+P"],
    "PrintPreview": ["Command+Shift+P"],
    "QuickPreferences": ["Alt+F12"],
    "Redo": ["Command+Y","Command+Shift+Z"],
    "Reload": ["F5","Command+R"],
    "ReloadFrame": ["Alt+F5"],
    "ReopenLastClosedTab": ["Command+Shift+T"],
    "ResetZoom" :["Mul", "Command+0", "Command+Num0"],
    "Save" : ["Command+S"],
    "SelectAll": ["Command+A"],
    "SelectPreviouslyActiveTab": ["Ctrl+Grave"],
    "SelectTabToTheRight": ["Ctrl+Tab"],
    "SelectTabToTheLeft": ["Ctrl+Shift+Tab"],
    "ShowContextMenu": ["Command+Shift+M"],
    "ShowHelp" : ["Command+Shift+OemSlash"],
    "SwitchToNextPage": ["Command+Shift+Right"],
    "SwitchToPreviousPage": ["Command+Shift+Left"],
    "ToggleFullscreen": ["Command+Shift+F"],
    "ToggleKeyboardSelection" : ["F7"],
    "ToggleOverstrike": ["Ins"],
    "Transfers": ["Command+J"],
    "Undo": ["Command+Z"],
    "ValidateSource": ["Command+Shift+U"],
    "ViewSource": ["Command+U", "Command+Alt+U"],
    "ZoomIn" : ["Command+OemPlus", "Command+Shift+OemPlus", "Shift+OemPlus", "Command+Plus", "Plus", "OemPlus"],
    "ZoomOut" : ["Command+OemMinus", "Command+Minus", "Minus", "OemMinus"]
  },
  "Advanced": {
    "Back": ["Z"],
    "FastForward": ["Shift+X"],
    "Find": ["OemSlash"],
    "FocusNextFrame": ["3"],
    "FocusPreviousFrame": ["Shift+3"],
    "Forward": ["X"],
    "LoadAllImages" : ["I"],
    "ResetZoom": ["6", "Num6"],
    "Rewind": ["Shift+Z"],
    "SelectNextElement" : ["D"],
    "SelectNextHeading" : ["S"],
    "SelectNextLink" : ["A"],
    "SelectPrevElement" : ["E"],
    "SelectPrevHeading" : ["W"],
    "SelectPrevLink" : ["Q"],
    "ShowAddressDropdown" : ["H"],
    "ShowImagesToggle": ["Shift+I"],
    "ZoomIn": ["0", "Num0"],
    "ZoomInMore": ["8"],
    "ZoomOut": ["9", "Num9"],
    "ZoomOutMore": ["7"]
  }
}

PHPでフィボナッチ数列を出力するソースコードを出力するプログラム

Quineみたいなものだけど、自身のソースコードを次々に書き換えて
それを新たに起動したPHPプロセスに標準入力として与えている。

fib.php

<?php
function php($input) {
    $process = proc_open('php', array(array('pipe', 'r'), array('pipe', 'w')), $pipes);
    if (is_resource($process)) {
        fwrite($pipes[0], $input);
        fclose($pipes[0]); 
    
        $output = stream_get_contents($pipes[1]);
        fclose($pipes[1]);
        proc_close($process);
    
        return $output;
    }
}
function callback($output) {
    $n = 50;
    $lines = explode("\n", trim($output));
    $count = count($lines);
    $lines[] = end($lines) + prev($lines);
    $f = __FILE__;
    $s = file_get_contents($f);
    $s = preg_replace("/__FILE__[;]/", "'$f';", $s);
    $s = preg_replace('/0\n1\n/', implode("\n", $lines), $s);
    return $count < $n ? php($s) : end($lines);
}
ob_start("callback") ?>
0
1
<?php ob_end_flush() ?>

Result

$ time php fib.php 
12586269025
php fib.php  0.51s user 0.28s system 92% cpu 0.851 total

あなたが学ぶべき10のプログラミング言語

純粋関数型言語は当然学ばなければなりません。
副作用の分離とモナドによる抽象化は本当のプログラマーなら知っておくべきでしょう。
遅延評価のメリット・デメリットとそれを活かしたアルゴリズムも重要です。

  • Scala

オブジェクト指向と関数型の機能を合わせ持ったマルチパラダイム言語のScalaを学ぶことは、あなたにとって新たな知見となるでしょう。
Twitterのインフラで使われるなど実績も十分で、現在のプログラマーにとっては当然のように使えるべき言語の1つです。
Haskellもまたそうですが、Scalaは型が強力なので型レベルプログラミングを学び、コンパイル時のエラー検出について考えてみるのもよいでしょう。

マルチコアのCPUが当たり前になった現在では、難しい並列処理をいかにして簡潔に実現するのかというのは非常に重要なテーマです。
Erlangは並列処理を念頭において開発された言語で、アクターモデルによる並列処理が特徴です。
アクターモデルによる新しい並列処理のアプローチは今後必ず重要になってくるので当然学ぶべきでしょう。
Rubyライクな記述のできるElixirを学ぶのもいいかもしれません。

HTML5が普及してWebアプリケーションの重要性増しており、JavaScriptの重要性もまた非常に高まっています。
プロトタイプベースのオブジェクト指向や、プロトタイプチェーンによる継承など、クラスベースのオブジェクト指向と違ったアプローチは学ぶ価値があるでしょう。
また関数が第一級のオブジェクトなので関数型のような記述も可能です。
関数型言語で学んだ知見はここでも多いに役立つでしょう。

歴史ある関数型のLISPやその方言のSchemeなどはプログラマーを名乗るのであれば書けて当然の言語でしょう。
S式による一貫した記法によってコードそものものを第一級のオブジェクトとして扱える柔軟性は他にはない素晴しいものです。
マクロによるプログラミングについても大いに学ぶことがあるでしょう。

歴史ある関数型言語MLから派生して生まれた、オブジェクト指向の機能を持った関数型言語です。
純粋な関数型言語Haskellとはまた少し違ったアプローチのOCamlを学ぶことで、関数型言語に対する理解がさらに深まるでしょう。

  • Coq

プログラムにはバグが付きものですが、バグを無くすにはどうすればいいでしょう。
テストを書けばテストケースに漏れがない限りはプログラムの品質を保証できます。
しかし、定理証明系のCoqを使えば、プログラムの動作を完全に証明することもできます。
テスト駆動開発、ビヘイビア駆動開発に続く、証明駆動開発について学ぶことは新しい知見となるでしょう。

Templateを使ったGenericプログラミングや、constexprによるコンパル時実行、型推論、ラムダ式など先進的な機能がたくさん詰ったC++は是非学んでおきたい言語です。
ある程度の規模の高速なネイティブプログラムを開発しようと思うとCでは非力すぎるため、多くの場合C++が最良の選択肢でしょう。
高速なネイティブプログラムが必要となる場面というのは未だ多く、学ばなければならない言語の1つでしょう。

Luaはプログラムに組み込んで使うこと目的として開発されたJavaScriptライクなスクリプト言語です。
言語として特徴的なのは途中で処理を止めて再開することができるコルーチンを持っている所でしょう。
スクリプト言語でありながら動作が非常に高速で、プログラムに組込むDSLとして最適と言えます。
例えばプログラムの設定ファイルの記述をLuaで柔軟に行なえるようにするなど、DSLを組込みこんだ設計というのは学ぶべき価値があるものです。

Ivy Bridgeで作るフェニックス3号

4/29にIvy Bridgeが出るのでその構成のメモ。

4/30 追記

爆熱という噂なので3770Sを買ったけど、定格ならアイドル時30度、ロード時45度で全く問題なし。
ちなみにチップセットの温度はアイドル時もロード時も32度。

Contac 30+の金具が何故かベタベタしていたのは謎。

smart J05の静音フィルターはオプションでいい。
そもそも無意味だし、すぐ傷つくし、あいつのせいで裏配線用の領域が狭くなる。

あと芯のケースファンがかなり煩さかったのでNF-P12 PWMに変更した。

SKK用の2ch顔文字辞書を作る

2chの一行AAの顔文字辞書は、MatsuConにいいのがあるけど、SKK用がない。

なのでHaskellで変換ツールを書いた。
Google日本語入力用の辞書(UTF-8なので)をソースにして、以下のように使える。
最後にskkdic-expr2をしてるのは、文字コードEUC-JPに変換してるのでソートしなおす必要があるため。

$ runghc skkdic-from-imedic.hs < google_std.txt | nkf -ex | skkdic-expr2

Linux(X11)でKensingtonのExpert Mouse 7を使う

KensingtonのExpert Mouse 7(EM7)には4つボタンがあり、以下のようにレイアウトされています。

.----------. .---------.
| 2:Middle | | 8:Back  |
`----------' `---------'
.----------. .---------.
| 1:Left   | | 3:Right |
`----------' `---------'

EM7にはスクロールホイールがないため、左上が中央ボタンで、右上が戻るボタンという変則的なレイアウトになっているようです。
このままでは使いづらいので、左上を戻るボタン、右上を進むボタンに設定します。ドライバはevdevを使ってxorg.confの該当セクションにButtonMappingを以下のように記述します。

	Option "ButtonMapping" "1 8 3 4 5 6 7 9 2"

これで一般的な5ボタンマウスのレイアウトになりました。

.--------. .-----------.
| 2:Back | | 8:Forward |
`--------' `-----------'
.--------. .-----------.
| 1:Left | | 3:Right   |
`--------' `-----------'

注意すべきなのは、ButtonMappingでボタンのレイアウトを変えてもインデックスは変わらないという点です。

機能の割り当て

次に、各ボタンに機能を割り当てていきます。

EM7にはスクロールリングが付いていますが、ボタンを押しながらボールを転がすことでスクロールができるとより便利です。自分は、文章をじっくり読むときはスクロールリング、長いページから目当ての情報を探しだすときはボールでスクロールと使い分けています。ここでは、右上のボタン(8:Forward)をスクロールボタンに割り当てています。

	Option "EmulateWheel" "true"
	Option "EmulateWheelButton" "8"
	Option "EmulateWheelInertia" "20"
	Option "XAxisMapping" "6 7"
	Option "YAxisMapping" "4 5"

続いて、先程ButtonMappingで潰してしまった中央ボタンを、左右の同時クリックに割り当てます。

	Option "Emulate3Buttons" "true"

しかし、この設定だけでは意図した通り動作せず、実際には中央ボタンではなく戻るボタンが割り当てられてしまいます。

ここで一旦Emulate3Buttonsの動作を確認してみます。

  1. 左右の同時クリック検知する
  2. "ボタン2"が押されたというイベントを生成
  3. xf86PostButtonEvent()でイベントをポストする

ここで問題となるのが、xf86PostButtonEvent()がボタンの種類ではなくインデックスを取る点です。つまり、ButtonMappingでボタン2を別のボタンに置き換えてしまうと、Emulate3Buttonsで呼ばれるボタンもまた変化してしまいます。

これを修正するにはxf86PostButtonEvent()が呼ばれる前にMappingテーブルを走査して、中央ボタンが割り当てられたインデックスを探し出す必要があります。毎回テーブルを走査するのは無駄なので予めインデックスを格納しておけばよさそうですが、ButtonMappingはxmodmapなどでリアルタイムに変更できるので、それもまた問題があります。

とりあえず面倒なので、evdevのソースに中央ボタンを割り当てたインデックス"9"を決め打ちしました。以下にそのパッチを掲載します。

追記

ちゃんとしたパッチ書きました。

diff --git a/src/emuMB.c b/src/emuMB.c
index 764b30e..287edc6 100644
--- a/src/emuMB.c
+++ b/src/emuMB.c
@@ -96,7 +96,7 @@ static signed char stateTab[11][5][3] = {
     {  0,  0,  0 },   /* nothing -> ground (no change) */
     {  0,  0,  1 },   /* left -> delayed left */
     {  0,  0,  2 },   /* right -> delayed right */
-    {  2,  0,  3 },   /* left & right (middle press) -> pressed middle */
+    {  9,  0,  3 },   /* left & right (middle press) -> pressed middle */
     {  0,  0, -1 }    /* timeout N/A */
   },
 /* 1 delayed left */
@@ -104,7 +104,7 @@ static signed char stateTab[11][5][3] = {
     {  1, -1,  0 },   /* nothing (left event) -> ground */
     {  0,  0,  1 },   /* left -> delayed left (no change) */
     {  1, -1,  2 },   /* right (left event) -> delayed right */
-    {  2,  0,  3 },   /* left & right (middle press) -> pressed middle */
+    {  9,  0,  3 },   /* left & right (middle press) -> pressed middle */
     {  1,  0,  4 },   /* timeout (left press) -> pressed left */
   },
 /* 2 delayed right */
@@ -112,12 +112,12 @@ static signed char stateTab[11][5][3] = {
     {  3, -3,  0 },   /* nothing (right event) -> ground */
     {  3, -3,  1 },   /* left (right event) -> delayed left (no change) */
     {  0,  0,  2 },   /* right -> delayed right (no change) */
-    {  2,  0,  3 },   /* left & right (middle press) -> pressed middle */
+    {  9,  0,  3 },   /* left & right (middle press) -> pressed middle */
     {  3,  0,  5 },   /* timeout (right press) -> pressed right */
   },
 /* 3 pressed middle */
   {
-    { -2,  0,  0 },   /* nothing (middle release) -> ground */
+    { -9,  0,  0 },   /* nothing (middle release) -> ground */
     {  0,  0,  7 },   /* left -> released right */
     {  0,  0,  6 },   /* right -> released left */
     {  0,  0,  3 },   /* left & right -> pressed middle (no change) */
@@ -141,33 +141,33 @@ static signed char stateTab[11][5][3] = {
   },
 /* 6 released left */
   {
-    { -2,  0,  0 },   /* nothing (middle release) -> ground */
-    { -2,  0,  1 },   /* left (middle release) -> delayed left */
+    { -9,  0,  0 },   /* nothing (middle release) -> ground */
+    { -9,  0,  1 },   /* left (middle release) -> delayed left */
     {  0,  0,  6 },   /* right -> released left (no change) */
     {  1,  0,  8 },   /* left & right (left press) -> repressed left */
     {  0,  0, -1 },   /* timeout N/A */
   },
 /* 7 released right */
   {
-    { -2,  0,  0 },   /* nothing (middle release) -> ground */
+    { -9,  0,  0 },   /* nothing (middle release) -> ground */
     {  0,  0,  7 },   /* left -> released right (no change) */
-    { -2,  0,  2 },   /* right (middle release) -> delayed right */
+    { -9,  0,  2 },   /* right (middle release) -> delayed right */
     {  3,  0,  9 },   /* left & right (right press) -> repressed right */
     {  0,  0, -1 },   /* timeout N/A */
   },
 /* 8 repressed left */
   {
-    { -2, -1,  0 },   /* nothing (middle release, left release) -> ground */
-    { -2,  0,  4 },   /* left (middle release) -> pressed left */
+    { -9, -1,  0 },   /* nothing (middle release, left release) -> ground */
+    { -9,  0,  4 },   /* left (middle release) -> pressed left */
     { -1,  0,  6 },   /* right (left release) -> released left */
     {  0,  0,  8 },   /* left & right -> repressed left (no change) */
     {  0,  0, -1 },   /* timeout N/A */
   },
 /* 9 repressed right */
   {
-    { -2, -3,  0 },   /* nothing (middle release, right release) -> ground */
+    { -9, -3,  0 },   /* nothing (middle release, right release) -> ground */
     { -3,  0,  7 },   /* left (right release) -> released right */
-    { -2,  0,  5 },   /* right (middle release) -> pressed right */
+    { -9,  0,  5 },   /* right (middle release) -> pressed right */
     {  0,  0,  9 },   /* left & right -> repressed right (no change) */
     {  0,  0, -1 },   /* timeout N/A */
   },

これで左右同時押しが正しく動作するようになりました。

最後にxorg.confのEM7のセクションをまとめて掲載しておきます。

Section "InputClass"
	Identifier "Mouse0"
	MatchIsPointer "on"
	MatchProduct "Kensington Expert Mouse"
	Option "ButtonMapping" "1 8 3 4 5 6 7 9 2"
	Option "Emulate3Buttons" "true"
	Option "EmulateWheel" "true"
	Option "EmulateWheelButton" "8"
	Option "EmulateWheelInertia" "20"
	Option "XAxisMapping" "6 7"
	Option "YAxisMapping" "4 5"
EndSection

鳥Haskellerコンテスト

  • 副作用が無いと俺はプログラミングも出来ないのかよ
  • もう半分くらい正格評価をしている、速くなるのかこれで
  • 悪いね、純粋関数型言語
  • 参照透明性だけは一流のところをみせてやるぜ
  • 遅延評価だぜ、信じらんねぇ
  • 型は推論した、でもこれじゃだめなんだろ
  • Haskellの評価戦略は晴れ時々大荒れ いいね、いい評価戦略だよ
  • Monadを…Monadを使うんだ…!
  • スペースリークしてる・・・分かってる! うぅぅわあああああ!!
  • unsafePerformIOだと!!うぅうわあああああああ!!!
  • かかか型推論がああああ!!うっっごけええええ!!
  • ああー!遅いっ!
  • 自動導出!自動導出せんかああ!