Slim3 の Scala 版を作りかけて、途中で時間がとれなくなり、いつかリリースしようと思いつつも、Google App Engine への興味を失い放置されていたコード片をアップしました。
https://github.com/m4i/slim3scala
結構な時間をかけて Scala のコンパイラとか、SBT のすごい読みにくいソースを読んだりしてたのに、公開しないのももったいないので。meta クラスの生成みたいなのがんばった記憶がある。
Slim3 の Scala 版を作りかけて、途中で時間がとれなくなり、いつかリリースしようと思いつつも、Google App Engine への興味を失い放置されていたコード片をアップしました。
https://github.com/m4i/slim3scala
結構な時間をかけて Scala のコンパイラとか、SBT のすごい読みにくいソースを読んだりしてたのに、公開しないのももったいないので。meta クラスの生成みたいなのがんばった記憶がある。
Gemfile
group :development, :test do gem 'plymouth', require: false gem 'pry-exception_explorer' gem 'pry-nav' gem 'pry-remote' gem 'pry-stack_explorer' end
breakpoint
binding.pry_remote
connect
$ bundle exec pry-remote
Gemfile
group :development, :test do gem 'ruby-debug19' gem 'ruby-debug-base19x', '>= 0.11.30.pre10' gem 'linecache19', git: 'https://github.com/mark-moseley/linecache.git', ref: '869c6a65155068415925067e480741bd0a71527e' end
initializer
require 'ruby-debug' Debugger.settings[:autoeval] = true Debugger.settings[:autolist] = 1 Debugger.settings[:reload_source_on_change] = true Debugger.start_remote
breakpoint
debugger
connect
$ bundle exec rdebug --client
rdebug --client からは利用できなかったrspec --no-drb -r plymouth specpry ヤバイ
もう2ヶ月近く前ですが、omniauth-runkeeper を公開しました。
https://rubygems.org/gems/omniauth-runkeeper
https://github.com/m4i/omniauth-runkeeper
OmniAuth の作者(社)が作った omniauth-github と同じ OAuth 2.0 なのでそれをベースにしました。
Nike+ から RunKeeper へのインポートアプリを作ろうと思って作ったのに、そっちは全く手付かず。
screen から tmux に乗り換えて2ヶ月ほど立ちますが、不便なことが4つありました。
(1), (2) は未だに未解決ですが、
(3) は 「cdd を tmux, bash, multi session +α に対応した」で解決、
今回は先日解決した (4) について書こうと思います。
先日 .tmux.conf を整理しようと man tmux を眺めていたんですが、どこからかコピペしてきた begin-selection や copy-selection が man に載ってないことに気づきました。どうやら key-table を指定した際に使用可能なコマンドは基本的に載っていないようです。
そこでソースを検索してみたところ、mode-key.c に見たことのないコマンドが大量あり、copy-line といういかにもそれっぽいコマンドを見つけました。
例えば、
bind-key -t vi-copy Y copy-line
で vim や screen と同じように Y で1行コピーが出来るようになります。(tmux 1.5 以上)
最後に tmux 1.6 の mode-key.c からコマンド一覧を以下に抜粋しておきます。
それぞれの使い方についてはまとまった説明は見つけられなかったので、名前から推測するか、検索するか、ソースを読むのが良いと思います。
key-bind -t vi-edit/emacs-edit で使えるコマンド
| backspace | cancel | complete | cursor-left |
| cursor-right | delete | delete-line | delete-end-of-line |
| delete-word | end-of-line | enter | history-down |
| history-up | next-space | next-space-end | next-word |
| next-word-end | paste | previous-space | previous-word |
| start-of-line | switch-mode | switch-mode-append | transpose-chars |
key-bind -t vi-choice/emacs-choice で使えるコマンド
| cancel | choose | down | page-down |
| page-up | scroll-down | scroll-up | up |
key-bind -t vi-copy/emacs-copy で使えるコマンド
| back-to-indentation | bottom-line | cancel | clear-selection |
| copy-line | copy-end-of-line | copy-selection | cursor-down |
| end-of-line | goto-line | history-bottom | history-top |
| jump-forward | jump-again | jump-reverse | jump-backward |
| jump-to-forward | jump-to-backward | cursor-left | rectangle-toggle |
| middle-line | page-down | next-space | next-space-end |
| next-word | next-word-end | page-up | previous-space |
| previous-word | cursor-right | scroll-down | scroll-up |
| search-again | search-forward | search-reverse | search-backward |
| select-line | start-number-prefix | start-of-line | begin-selection |
| top-line | cursor-up |
以下のコードをサイドバーとして追加
<script>
(function($) {
var $module_body = $('.hatena-module-body:last');
$module_body.parent()
.removeClass('hatena-module-html')
.addClass('hatena-module-categories')
.prepend($('<div>').addClass('hatena-module-title').text('カテゴリー'));
$.get('/categories').done(function(html) {
$module_body.html(html.replace(
/[\s\S]*<div class="entry-content">\s*|\s*<\/div>[\s\S]*/g, ''));
});
})(jQuery);
</script>
https://github.com/m4i/hatenablog-snippets/blob/master/category.js
他にもいくつかカテゴリ一覧を表示するコードが紹介されていますが、このコードは以下の点で優れています。
自分でメンテナンスしなくても使用しているカテゴリが自動でリストアップされます。
カテゴリ一覧は /categoies から取得しています。
プロフィール、検索、リンクなどと同じように、以下のような HTML 構造になっています。
<div class="hatena-module hatena-module-categories">
<div class="hatena-module-title">カテゴリー</div>
<div class="hatena-module-body">
<ul>
<li>カテゴリー1</li>
<li>カテゴリー2</li>
</ul>
</div>
</div>
なので、既存のテーマと相性が良かったり、将来カテゴリモジュールが実装された時に CSS の修正が少なくて済むと思います。
利用例はこのブログの最下部で見れます。お好みで適当に CSS を書いてください。
はてなブログでははてな記法の実装がはてなダイアリーと違うようで、動かない記法がいくつかあります。*1
続きを読む記法 もその内の一つです。
はてなダイアリーで書いていたときは使ったこともなかったんですが、最近立て続けに長めの記事を書いたら、トップページが長くなりすぎて見難くなってしまったので、無理やり使えるようにしてみました。
動作確認のためにこの下に続きを読む記法を書いてみますので、トップページなどから確認してみてください。
(この上)
どうやって実現するかですが、==== を記述した部分には以下の HTML が挿入されるようです。
<div class="seemore">
ですので、これ以降の要素をすべて削除し、「続きを読む」のリンクを設置してあげれば OK です。
そこで以下のコードを書きました。これをサイドバーにコピペすれば使えるようになります。
<script>
(function($) {
if (!(location.pathname === '/' ||
location.pathname.indexOf('/category/') === 0)) return;
function pathname(url) {
return url.replace(/^https?:\/\/[^\/]*|[#?].*$/g, '');
}
$('article.entry').each(function() {
var $seemore = $(this).find('div.entry-content div.seemore');
if ($seemore.length === 0) return;
var url = $(this)
.find('header.entry-header a.entry-title-link').attr('href');
var $a = $seemore.find('a');
if ($a.length === 1 && pathname($a.attr('href')) === pathname(url)) return;
var $tail = $('<a>')
.addClass('seemore')
.attr('href', url)
.text('続きを読む')
.prependTo($seemore);
while (!$tail.hasClass('entry-content')) {
$tail.nextAll().detach();
$tail = $tail.parent();
}
});
})(jQuery);
</script>
https://github.com/m4i/hatenablog-snippets/blob/master/seemore.js
2012-02-13: カテゴリページに対応
*1:この脚注記法も脚注が表示されず、tooltip を読むしかありません。逆に gist 記法のような新しいものもあります。
Gyazo というサービスがあります。
スクリーンショットを共有するためのウェブサービスで、撮ったあとにその URL を共有したい人に送るだけで画像を簡単に共有することができます。
その際の画像の URL は次のようになっています。
http://gyazo.com/587011ed4b960eff36ef351efe393e37
Gyazo というアプリケーションの性質上、このURLが推測可能なものであってはいけません。
Gyazo は画像を特定する部分の文字列が32文字で、この文字列は長ければ長いほど推測が難しくなります。
これを8文字にしてはいけないのでしょうか?8文字であったら口頭で伝えることも可能で、新たな利用方法が生まれるかもしれません。
逆に32文字で本当に推測不可能と言えるのでしょうか?本当は1024文字必要なところをコピペの利便性を考えて32文字にしてしまっているのではないでしょうか。
今回は、この文字列をどの程度まで短くしても推測不可能と言えるのか考えてみたいと思います。
ちなみに数学に関しては高校の知識も危ういので、間違っている可能性があります。そのときはぜひ指摘していただけたらと思います。
この先を読み進める前に、自分がこのサービスを作るとしたらどの程度の文字数にするか考えてみると面白いかもしれません。8文字は明らかにダメだろうと思う方は12文字ではどうでしょうか?16文字は?それとも32文字では不安だから64文字くらいにしますか?
推測不可能な文字数を決めるためには以下の3つの値をそれぞれ自分で見積もる必要があります。
ここでは
と仮定して考えてみたいと思います。
仮に8文字だとして考えてみましょう。
Gyazo の場合どうやら16進数のようですので 通りの URL が存在しうることになります。
画像の数は ですので全体の4分の1が利用されることになります。
これでは直感的にもすぐに URL を探し当てられてしまいそうですね。
この簡単な例でどうやって確率を求められるのか式を考えてみましょう。
1回適当な URL を入力するだけで 25% の確率で見つかってしまいます。式は
ですね。
2回試した場合はどうでしょうか?
なんか一気に難しくなった気がしないでもないですが、答えはそれっぽいですね。
なのかもしれませんが、最大でも 程度の試行回数なので、今回はわかりやすくするため上の式で近似…でも問題ないでしょうか?
10回試して正しい URL が発見される確率は
です。
つまり8文字では 回の試行を
以下に抑えるなんて到底難しそうです。
ここから9文字の場合はどうか、10文字の場合はどうかとやっていっても時間がかかるので、この条件をみたす文字数を x とおきましょう。
それを先ほどの計算式に当てはめてみます。
これを x を求める式に変形してみましょう。
これくらいは簡単ですよね?
もちろん私はグーグル先生に聞きました。
m, n, p にそれぞれ値を代入して計算してみましょう。Ruby だと
m = 2 ** 30 n = 2 ** 20 p = 1.0 / 2 ** 14 Math.log(m / (1 - (1 - p) ** (1.0 / n)), 16) => 15.999988993278293
となりました。ということは
ですので、文字数が16文字あれば見積もった条件を満たすことになります。
このサービスは少人数で短期間使うだけだし、せいぜい人力で URL 入れてみるくらいの人しかいないと考えて以下の条件にしてみます。
この場合
となり、6文字で済むことになります。
そもそも URL が16進数でなくてはいけない理由はないし、もっと短くしたいと思えば、文字の種類を増やせば短くできるかもしれません。
62なんて16の約4倍なんだから、16文字必要だったところが4文字で済んでもいいのではないかと期待が膨らみます。
では計算してみましょう。
数字 + 英小文字: 36
数字 + 英字: 62
13文字と11文字で期待したほどではないかもしれませんが、短くすることが出来ました。