Excel や Numbers、Google Spreadsheet からコピーした表を Markdown としてペーストする【CotEditor】
はじめに
昨今の Markdown 界はどうなっているだろうかとネットサーフィンをしていると、最近はこのようなエディタが人気らしいではないですか。
ふむふむ、これは良い WYSIWYG ですね。ていうか、ここまでする?
表のペースト機能がすごい
「Excel の表をコピーしてペーストすると自動的に Markdown の表になる」という機能に驚かされました。
これは良い。なんという逆転の発想。コピーするときに Markdown 文字列に変換するのではなく、ペーストする瞬間に処理を行う。これなら Excel だろうが Numbers だろうが Google Spreadsheet だろうが関係ありません。好きなスプレッドシートを使うことができます。もう、あっちは VBA、こっちは AppleScript で、向こうは JavaScript なんて考えなくて済みます。
何を驚いているんだい?そもそも初めから本来こうあるべきだろう?
そんなスティーブ = ジョブズの名言が聞こえてくるようです。1
CotEditor スクリプトを作ってみる
クリップボードから TSV 文字列を取り出すのは pbpaste
コマンドがやってくれますから、それを加工する処理だけ、好きなスクリプト言語を使って作れます。
ファイル名を「TSVを表としてペースト.@$v.php」なんてファイル名で CotEditor のスクリプトフォルダに入れれば、「⌘ + Shift + V」で実行できます。
使い方
表計算ソフトからセル範囲を選択して「コピー」を行います。
CotEditor に戻って「⌘ + Shift + V」します。以下のようになります。
Id |Name |Price ------|----------------|------------ 1 |Apple |200 2 |Banana |150 3 |Citrus |300 九九九|ドラゴンフルーツ|価格未設定。
スクリプトのソースコード
#!/usr/bin/php -q <?php // %%%{CotEditorXInput=Selection}%%% // %%%{CotEditorXOutput=ReplaceSelection}%%% mb_detect_order("UTF-8,SJIS,sjis-win"); // 文字列の長さを、全角:2、半角:1 で数える。 function jp_str_len($str) { $len = 0; foreach (preg_split('//u', $str, null, PREG_SPLIT_NO_EMPTY) as $chr) { if (mb_ereg_match("[ -~]", $chr)) { $len += 1; } else { $len += 2; } } return $len; } // 文字列の長さを、全角:2、半角:1 として PAD する。 function jp_str_pad($input, $pad_length, $pad_string = " ", $pad_style=STR_PAD_RIGHT) { $input_len = jp_str_len($input); $pad_len = $pad_length - $input_len; $pad = str_repeat($pad_string, $pad_len); $ret = ""; if ($pad_style === STR_PAD_RIGHT) { $ret = $input . $pad; } else { $ret = $pad . $input; } return $ret; } // ペーストボード取得 $pb = mb_convert_encoding(`pbpaste`, 'UTF-8', 'SJIS'); //$pb = `pbpaste`; // 入力チェック if (strpos($pb, "\n") === false && strpos($pb, "\t") === false) { $msg = "改行/タブのいずれも含まれていないようです。"; $title = "クリップボードの内容は TSV ではありません"; `osascript -e 'display notification "$msg" with title "$title"'`; exit(0); } // 行分割 $linesSrc = explode("\n", $pb); // 列分割 $lines = []; foreach ($linesSrc as $line) { $lines[] = explode("\t", $line); } // 列幅取得 $colWidth = []; for ($i = 0; $i < count($lines[0]); $i++) { foreach ($lines as $line) { $c = $line[$i]; $w = jp_str_len($c); $colWidth[$i] = max($w, $colWidth[$i]); } } // 配列全体 PAD 関数定義 $pad_string = ' '; $array_pad_fnc = function ($text, $cidx) use ($colWidth, &$pad_string) { $pad = jp_str_pad($text, $colWidth[$cidx], $pad_string, STR_PAD_RIGHT); return $pad; }; // 出力関数定義 function echo_markdown_line($ary) { echo implode('|', $ary) . "\n"; } // 見出し出力 $titles = array_map($array_pad_fnc, $lines[0], range(0, count($lines[0])-1)); echo_markdown_line($titles); // 水平線出力 $pad_string = '-'; $tmp = array_fill(0, count($colWidth), '-'); $hr = array_map($array_pad_fnc, $tmp, range(0, count($tmp)-1)); echo_markdown_line($hr); // データ出力 $pad_string = ' '; for ($i = 1; $i < count($lines); $i++) { $colTxt = $lines[$i]; $cols = array_map($array_pad_fnc, $lines[$i], range(0, count($lines[$i])-1)); echo_markdown_line($cols); }
環境
以下の環境で開発・動作確認しました。
ProductName: Mac OS X ProductVersion: 10.15.7 BuildVersion: 19H1323 PHP 7.3.11 (cli) (built: Jun 5 2020 23:50:40) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.3.11, Copyright (c) 1998-2018 Zend Technologies CotEditor version: 2.7.4 Numbers.app version: 10.3.9
また、Google Spreadsheet でも確認しました。
CotEditor のスクリプトで動かした時のみ、pbpaste
の結果を SJIS
から UTF-8
に変換しないといけないのが、何となく納得できませんでした。Numbers.app 以外のアプリケーションから取得すると、また違うのかもしれません。
- Disk Burner(Power to Burn)の発表時だと思いますが、出典を見つけることはできませんでした。↩