UTF-8でpbcopyできるようにする

単に環境変数を追加するだけで大丈夫みたい (pbcopyで日本語もコピーできるようにする - テックノート@ama-ch )。 ちゃんとテストしてないけど複数のソースでそんなことが書いてあるのを読んだので、たぶん大丈夫だと思う。下のやつは用無しになるけど一応置いておく。
やっぱ環境変数を変えるのはよくない。ターミナルから open -n /Applications/Firefox.app がエラーを吐くようになったりしてしまった。

最良の方法が見つかった。コメント欄うめさんに感謝。

alias pbcopy="nkf -w | __CF_USER_TEXT_ENCODING=0x$(printf %x $(id -u)):0x08000100:14 pbcopy"

以下は既に用無し。

UTF-8 で pbcopy/pbpaste するための Wrapper

Mac OS Xの標準関数pbcopy/pbpasteは非常に便利なのだが、日本語が混じると途端に使いにくくなる。というわけで、ラッパースクリプトを書いた。

  • upbcopy.sh
#!/bin/sh
# __CF_USER_TEXT_ENCODINGを適当な値に変える。
me=`id -g`
__CF_USER_TEXT_ENCODING=0x`printf "%X" $me`:0x8000100:0x8000100
export __CF_USER_TEXT_ENCODING

#pbcopy の挙動をエミュレート
LF='
'
if [ "$1" == "-a" ]; then
    shift
    TEXT=$*$LF
else
    while read -r i; do
        TEXT=$TEXT$i$LF
    done
fi

/bin/echo -n "$TEXT" | /opt/local/bin/nkf -w | /usr/bin/pbcopy

/opt/local/bin/nkfMacPorts でインストールしたnkf

これで普通の pbcopy と同じように、

% echo あいうえお | upbcopy.sh
% cat aiueo.txt | upbcopy.sh

などとできる。使い方は極力普通の pbcopy に合わせたつもり。

さらに、-a フラッグを立てると、

% upbcopy.sh -a あいうえお

と出来るようにもしてある。


ついでに pbpaste のほうも、有用かどうかは知らないが、ほぼ同じなので書いておいた。

  • upbpaste.sh
#!/bin/sh
me=`id -g`
__CF_USER_TEXT_ENCODING=0x`printf "%X" $me`:0x8000100:0x8000100
export __CF_USER_TEXT_ENCODING

/usr/bin/pbpaste

参考にしたページ (主に自分用のメモ)

ちょっと検索したところ、

cat /tmp/scr|nkf -s|pbcopy とかでオケ。

はじめてのにき(2007-03)

とか、

ちなみにpbcopyとpbpasteと同様に日本語の文字列はISO-2022-JP以外のエンコーディングだとコピペできなくなります。これは受け取った文字列をNSPasteboardに渡す時、文字列はNSStringで渡すのですがこのNSStringを初期化する時にシステムのデフォルトエンコーディングで文字列を喰っている為、正しく内部エンコーディングに変換できないからです。

MODULE.JP - ShellからMac OS Xのクリップボード弄り

とか書いてあるのも見つけたのだが、自分のところでは無理だった。

これはおそらく、自分のシステム言語が英語になっていて、~/.CFUserTextEncoding と環境変数 $__CF_USER_TEXT_ENCODING が日本語環境とは違うからだろう。

% cat ~/.CFUserTextEncoding 
0:0
% echo $__CF_USER_TEXT_ENCODING
0x1F6:0:0

またしばらく検索していると、下のような手掛かりも見つけた。

問題は Carbon のプログラムで, LANG とは別の __CF_USER_TEXT_ENCODING という環境変数を参照している。 これはログイン時に ~/.CFUserTextEncoding の値をもとに設定されており, 日本語環境では 1:14 になっているが, この「1」が MacJapanese つまり Shift_JIS 系統のエンコーディングをあらわす。 そのため, たとえばコマンドラインからクリップボードを操作する pbcopy / pbpaste のようなコマンドは, 文字列を MacJapanese で扱うことになり, 文字化けをひきおこす。 kCFStringEncodingUTF8 は 0x08000100 なので, ~/.CFUserTextEncoding を 「0x08000100:14」 に書きかえてログインしなおしたら, とりあえず pbcopy / pbpaste は UTF-8 で動くようになった。

massangeana のいろいろ :: Mac Pro を買った (6) UTF-8 を使用する

まとめると、

  • pbcopy/pbpasteは、環境変数$__CF_USER_TEXT_ENCODINGよりも、~/.CFUserTextEncodingの中身を設定として優先するらしい
  • 環境変数$__CF_USER_TEXT_ENCODINGをpbcopyは見てるけど、pbpasteはなんだか怪しくて、GUIアプリとpbpaste間の日本語の受け渡しがうまく行かないっぽい

したがって、pbcopy/pbpasteをUTF-8で使う時の処方箋は、

echo 0x08000100:14 > ~/.CFUserTextEncoding
#意味:コロンの前の数字はエンコーディングでUTF-8を表し、後ろの数字が使用している言語で日本語を表す
CFUserTextEncoding - ATP合成日誌

ただ、~/.CFUserTextEncodingを書き換える方法だと、特定のプログラムが立ち上がらないなどの問題があるようなので、ちょっと躊躇していたところ、以下の決定的なヒントを見つけた。

Add to ~/.cshrc or ~/.tcshrc (for tcsh)

setenv __CF_USER_TEXT_ENCODING '0x1F5:0x8000100:0x8000100'

Add to ~/.profile (for bash)

__CF_USER_TEXT_ENCODING=0x1F5:0x8000100:0x8000100
export __CF_USER_TEXT_ENCODING

("export __CF_USER_TEXT_ENCODING=0x1F5:0x8000100:0x8000100" does not work for me, I don't know why.)
0x1F5 is the hex value of your user ID. It is said that you have to change it if yours is not 501. I'm a bit doubtful because 'SubEthaEdit.app/Contents/Resources/Scripts/61-DeHardwarp.scpt' seems to work in another account too.

LISTSERV 15.5 - NISUS Archives

直接は関係ないが、screen でも pbcopy できるとわかったので、使い勝手がずいぶん広がったような気がする。