zsh_historyにはASCII以外の文字がメタ文字を使ってエスケープされているので、適切にデコードしてからfishが読み取れるyamlに変換する。
convert.rb
require 'stringio'
File.open(File.expand_path('~/.zsh_history')) do |f|
escaped = StringIO.new
# .zsh_historyのデコード
f.to_enum(:each_byte).tap do |enum|
processes = []
loop do
b = enum.next
if b == 0x83
b = enum.next
b = (b ^ 0x20)
end
processes << b
end
escaped.write processes.pack('c*')
end
# 雑にパースしてfish_historyのyamlに変換
# ヒアドキュメントなどを使った複数行入力については諦めて標準エラー出力に出す
escaped.rewind
escaped.each_line do |l|
unless l[0] == ':'
$stderr.puts l
next
end
command = l.split(/;/, 2).last
time = l.split(/\:/, 3)[1]
if time.nil?
$stderr.puts l
next
end
puts "- cmd: #{command}"
puts " when: #{time.strip}"
end
end
$ ruby convert.rb > ~/fish_history
$ cat ~/fish_history >> ~/.local/share/fish/fish_history