zsh Goでzsh_historyをパースするプログラムを書いてみる zsh 文字化けしたzsh_historyファイルを読めるようにする, zsh マルチバイト文字をzsh_historyの形式に変換する の仕様に則って、パース処理を書いていく package zhistconv const ( // zsh_historyの仕様で、各バイトが0x83~0xA2のとき、その前に0x83を入れて6bit目を反転させる x83 = 131 xA2 = 162 x20 = 32 ) // zsh_historyを読める形式に変換する func ParseZshHistory(latin1Byte []byte) []byte { isMarking := false var byteBuffer []byte for _, codePoint := range latin1Byte { if codePoint == x83 { isMarking = true continue } if isMarking { // 6bit目を反転させるために0x20をXORする invertCodePoint := codePoint ^ x20 byteBuffer = append(byteBuffer, invertCodePoint) isMarking = false } else { byteBuffer = append(byteBuffer, codePoint) } } return byteBuffer } // プレーンなテキストをzsh_historyに変換する func ConvertToZshHistory(latin1Byte []byte) []byte { var byteBuffer []byte for _, codePoint := range latin1Byte { // 131は0metacharの10進数表現 if x83 <= codePoint && codePoint <= xA2 { // 6bit目を反転させるために0x20をXORする invertCodePoint := codePoint ^ x20 byteBuffer = append(byteBuffer, x83) byteBuffer = append(byteBuffer, invertCodePoint) } else { byteBuffer = append(byteBuffer, codePoint) } } return byteBuffer }