✖
gerry++
✖
✖
もともと自分は Ruby 厨であるが、最近 Ruby は書き捨てのプログラムを書くのために使うにすぎず、ウェブアプリの言語としては Scala に注目しており、環境としては Perl を最も高い頻度で利用している。ねじれている。
Ruby はそれでも直感的にアルゴリズムに記述するのに最も優れていると感じていて、Google Developer Days の DevQuiz も、なんとなしに Ruby で書きはじめたりした。その他それなりに安定して中規模のアプリケーションを書くには Perl が最も安心できて、素直で自由に書けると感じている。とはいえ Perl は自由すぎるし、実行時まで何もかもが解らなくて、それなりに大きく継続運用するアプリケーションを書くときに不安があり、Scala に強い興味を持っているが、Scala を使う機会があんまりなかったり、環境整備がいまいちなのであんまり積極的に使っていない。ねじれている。
関連エントリー
- ✖ Scala で書いてる個人的なアプリケーションは、今月中にどこかでリリースしたいなぁ。書こうと思ってから数ヶ月経っているわけだし…… しかし...
- ✖ プログラミングですごい面白い方法が出てきたぞ! みたいなのが最近は全然なくて、いやあるのかもしれないけれど、全然目に入ってこないか、入ってき...
- h2o での server-push タイミングの最適化 h2o は mruby ハンドラで link ヘッダを使って push を指示すると、バックエンドへの問合せと非同期で静的ファイルを pus...
- nginx の rewrite ルールっぽく h2o の mruby でリクエストの rewrite を行う このサイトのHTTPS化にあたって nginx で書いていた rewrite のルールを h2o の mruby で処理するように変える必要...
- CSRF 防止用トークンの自動チェックの問題と解決 自分が作るウェブアプリケーションでは基本的に以下のような規則を守るようにしている GET だけで副作用 (DB書きこみなど) を伴う処理をし...
git-branch-recent の高速化
.git/refs 以下の mtime を見ることで高速化をした。clone 直後はもしかするとズレたりするかもしれないので heavy バージョンも -s をつけることで実行できるようにした。
#!/usr/bin/env ruby -Ku
require 'pathname'
require "optparse"
class GitRecentCommand
Ref = Struct.new(:hash, :name, :time, :rtime, :author, :subject)
def dot_git
@dot_git ||= Pathname.new(`git rev-parse --git-dir`.chomp)
end
def self.run(argv)
self.new.option(argv).run
end
def initialize(opts={})
@opts = {
:strict => false,
:max_num => 20,
}.update(opts)
end
def option(argv)
opts = @opts
argv = argv.dup
OptionParser.new do |parser|
parser.instance_eval do
self.banner = <<-EOB.gsub(/^\t+/, "")
Usage: #{$0} [opts]
EOB
separator ""
separator "Options:"
on("-s", "--strict", "Running on strict mode (very heavy)") do |foreground|
opts[:strict] = true
end
on("-n", "--number NUMBER", "Number branch to show") do |num|
opts[:max_num] = num.to_i
end
parse!(argv)
end
end
self
end
def run
details = @opts[:strict] ? recent_branches_strict : recent_branches_fast
details = details.sort_by {|ref| ref.time }.last(@opts[:max_num])
remote_master = nil
rtime_width = name_width = author_width = 0
details.each do |ref|
name_width = ref.name.size if ref.name.size > name_width
author_width = ref.author.size if ref.author.size > author_width
rtime_width = ref.rtime.size if ref.rtime.size > rtime_width
remote_master = ref.hash if ref.name == 'origin/master'
end
details.each {|ref|
ref.instance_eval {
out = "\e[32m% -#{name_width}s\e[39m % #{rtime_width}s %s \e[31m% -#{author_width}s\e[39m %s" % [
name,
rtime,
hash[/^.{7}/],
author,
subject
]
puts (hash == remote_master) ? "\e[7m#{out}\e[0m" : out
}
}
end
# search recent branches by file mtimes
def recent_branches_fast
refs = []
refs.concat Pathname.glob(dot_git + 'refs/heads/**/*')
refs.concat Pathname.glob(dot_git + 'refs/remotes/**/*')
branches = refs.reject {|r| r.directory? }.sort_by {|r| r.mtime }.last(@opts[:max_num]).map {|r|
ref = r.read.chomp
if name = ref[/ref: (.+)/, 1]
(dot_git + name).read.chomp
else
ref
end
}
retrieve_branch_details(branches)
end
# search recent branches by retrieving whole branch information
def recent_branches_strict
branches = `git branch -a`.gsub!(/^\*?\s+|\(no branch\)\s*/, "").split(/\n/).map {|i|
i.split(/ -> /)[0]
}
retrieve_branch_details(branches)
end
# retrieve branch details information from branch names
def retrieve_branch_details(branches)
details = []
IO.popen("-", "r+") do |io|
if io.nil?
args = [ "show", "--pretty=format:%H\t%d\t%ct\t%cr\t%an\t%s", *branches ]
args << "--"
exec "git", *args
else
while l = io.gets
next unless l =~ /^[a-z0-9]{40}/
hash, refs, time, rtime, author, subject = * l.chomp.split(/\t/)
refs.gsub!(/^\s*\(|\)\s*$/, '')
refs.split(/\s*,\s*/).each do |ref|
is_remote = ref[%r{refs/remotes}]
ref.gsub!(%r{refs/(remotes|heads)/}, '')
details.push Ref.new(hash, ref, time.to_i, rtime, author, subject)
end
end
end
end
details
end
end
GitRecentCommand.run(ARGV)
✖
✖
土曜日は植物園に。日曜日、橿原神宮に行こうと思っていたのに、起きたのが14:30ぐらいで遅すぎたのでやめた。変わりに、平安神宮、京都市立美術館、京都市立美術館別館にいった。毛筆で記名を求められて、普段鉛筆やペンさえ持たないのでかなりあせりつつ書いたら「筆遣いが~」と言われて嬉しい半分死にたくなった。別館のほうでは写真展を見た。一通りいくつか見たうえで、やっぱまともな組写真をやりたいなあと強く思った。
関連エントリー
✖
zsh で C-r したときスペースを補完語として入力できないという状況を回避するバッドノウハウ
zsh で C-r しているとき、スペースを補完語に使いたくても、スペースを入力した瞬間に bck-i-search: を抜けて、コマンド先頭にスペースが挿入されてしまうという状態になっていた。望む希望としては、スペースを入力したら、スペースも補完語として挿入されてほしい。
これはどうやら、自分で bindkey " " magic-abbrev-expand-and-insert というように、スペースキーに対して独自定義の関数を定義しているとそうなってしまうらしい。
zle_hist.c によると、bck-i-search の間のキー入力はハードコードで分岐していて、既に決まっているものについて書きかえるしかない。
なんとなく magic-space を上書きしてやったら、望む挙動になった。
# abbr
typeset -A abbreviations
abbreviations=(
"L" "| \$PAGER"
"G" "| grep"
"H" "$HOME/project/Hatena-"
"HE" "lib/**/Engine/"
"HM" "lib/**/MoCo/"
"HA" "lib/**/App/"
"HC" "lib/**/Config.pm"
"HEAD^" "HEAD\\^"
"HEAD^^" "HEAD\\^\\^"
"HEAD^^^" "HEAD\\^\\^\\^"
"HEAD^^^^" "HEAD\\^\\^\\^\\^\\^"
"HEAD^^^^^" "HEAD\\^\\^\\^\\^\\^"
# typo
"lkm" "lm"
"it" "git"
"gitp" "git"
"mysql" "mysql -unobody -pnobody -h"
)
magic-abbrev-expand () {
local MATCH
LBUFFER=${LBUFFER%%(#m)[-_a-zA-Z0-9^]#}
LBUFFER+=${abbreviations[$MATCH]:-$MATCH}
}
# BK
magic-space () {
magic-abbrev-expand
zle self-insert
}
magic-abbrev-expand-and-insert () {
magic-abbrev-expand
zle self-insert
}
magic-abbrev-expand-and-insert-complete () {
magic-abbrev-expand
zle self-insert
zle expand-or-complete
}
magic-abbrev-expand-and-accept () {
magic-abbrev-expand
zle accept-line
}
magic-abbrev-expand-and-normal-complete () {
magic-abbrev-expand
zle expand-or-complete
}
no-magic-abbrev-expand () {
LBUFFER+=' '
}
zle -N magic-abbrev-expand
zle -N magic-abbrev-expand-and-magic-space
zle -N magic-abbrev-expand-and-insert
zle -N magic-abbrev-expand-and-insert-complete
zle -N magic-abbrev-expand-and-normal-complete
zle -N magic-abbrev-expand-and-accept
zle -N no-magic-abbrev-expand
zle -N magic-space # BK
bindkey "\r" magic-abbrev-expand-and-accept # M-x RET できなくなる
bindkey "^J" accept-line # no magic
bindkey " " magic-space # BK
bindkey "." magic-abbrev-expand-and-insert
bindkey "^I" magic-abbrev-expand-and-normal-complete









