iTunes の曲名を一括置換する (macOS)

スクリプトエディタを使う。以前は AppleScript しか使えなかったが、現在では JavaScript で簡潔に書けるようになった。

次のスクリプトを実行すると、iTunes で選択したトラックの曲名を置換できる。

app = Application("iTunes");
app.selection().map((track) => {

	// 「J.S.Bach;Choral」→「J.S.Bach: Choral」のように置換
	track.name = track.name().replace(/;/, ": ");

	return track.name();
});

f:id:scientre:20190411205501p:plain
スクリプトエディタ

PDFの文字列をコピペするとおかしな文字列になる現象の本当の回避方法

Microsoft Office の Word, Excel, PowerPoint (2010, 2013, 2016 とも) から出力した PDF ファイルを Adobe ReaderAdobe Acrobat Pro で開くとテキストがうまくコピーできない。

たとえば、「毎日暑い日が続きますが、ご自愛くださいませ。」と書いたPDFがあるとします。


(中略)


不思議なことに「毎日暑いが続きます、ご自愛くださせ。 毎日暑いが続きます、ご自愛くださせ。 毎日暑いが続きます、ご自愛くださせ。 毎日暑いが続きます、ご自愛くださせ。 毎日暑いが続きます、ご自愛くださせ。 毎日暑いが続きます、ご自愛くださせ。 毎日暑いが続きます、ご自愛くださせ。 毎日暑いが続きます、ご自愛くださせ。 毎日暑いが続きます、ご自愛くださせ。 毎」などと何度も繰り返された文章になります。

PDFの文字列をコピペするとおかしな文字列になる現象の回避方法。 / 【エムテック】設計・人材派遣・WEBサイト制作・システム開発

ちなみに Microsoft Office から PDF を作成するときに「アクセシビリティ用のドキュメント構造タグ」を外すと正しくテキストをコピーできるらしいが、この設定をデフォルトにすることができず毎回設定する必要がある。それにテキストをコピーしたいのは自分だからわざわざ相手に頼むわけにもいかない。

実はこれを簡単に解決する方法があって、それは Adobe ReaderAdobe Acrobat を使わないこと。ちゃんとコピーできないのは Adobe のソフトに問題があるからだ。

Windows の場合、最近のウェブブラウザは独自で PDF を表示する機能を持っているので好みのウェブブラウザに PDF を関連付けよう。Edge, Firefox, Chrome を試してみたところ、Chrome が最も見た目通りにテキストをコピーできた。Edge や Firefox では改行が入らないことがある。

PDF を Chrome に関連付ける画面
PDF を Chrome に関連付ける

macOS の場合は標準で関連付けられている「プレビュー」を使えばよい。

dir でワイルドカードを使うと意図しないファイルがマッチする

dir コマンドの出力を使ったバッチファイルを作っていたところ、意図しないファイルが出力されていることに気づいた。「.csv」で終わるファイルのみを出力してほしいのだが、「.csv_header」で終わるファイルも出力されている。

> dir /b *.csv
1190.csv
1190.csv_header
shisetsu_toilet.csv
shisetsu_toilet.csv_header

原因

意図しないファイルにマッチする原因は MS-DOS や初期の Windows で使われていた 8.3 形式のファイル名にあった。ためしに 8.3 形式のファイル名も出力する「/x」オプションをつけて実行してみると、「.csv_header」というファイルが「...~1.csv」のように表現されていた。

> dir /x
…
2019/04/02  10:12             5,424              1190.csv
2019/04/02  10:35               939 1190~1.csv   1190.csv_header
2019/04/02  10:12         1,403,278 shiset~1.csv shisetsu_toilet.csv
2019/04/02  10:36               371 shiset~2.csv shisetsu_toilet.csv_header
…

dir コマンドではワイルドカードはこの 8.3 形式のファイル名にもマッチする。

解決方法 1 ― PowerShell を使う

Windows 7 からコマンドプロンプトに代わる新しいコマンドラインツールとして搭載された Windows PowerShell ではこの問題は発生しない。ただし別のプロセスからコマンドラインプログラムを呼び出すときはコマンドプロンプトが使用されてしまうため、この問題に対処できない。

解決方法 2 ― 8.3 形式のファイル名を生成しないようにする

コマンド側で 8.3 形式のファイル名にマッチさせない方法がないようなので、そもそも 8.3 形式のファイル名を生成させないことにした。

コマンドプロンプトまたは PowerShell を管理者として実行し、次のコマンドを実行する。

> fsutil 8dot3name set c: 1
8dot3name の生成が C: で無効になりました

8.3 形式のファイル名を削除する

設定はすぐに反映されるが、すでに生成された 8.3 形式のファイル名は削除されない。

コマンドプロンプトまたは PowerShell を管理者として実行し、次のコマンドを実行することで、カレントディレクトリ以下にあるファイルやフォルダの 8.3 形式ファイル名を削除できる。

> fsutil 8dot3name strip /v /s .


Twitter bot 鸚鵡ちゃんを Raspberry Pi 3 で動かす

鸚鵡ちゃんは2012年に Twitter 向けに書かれた bot で、タイムラインやリプライから言葉を覚え、覚えた言葉をたまにつぶやいたりリプライに反応したりする。最新の Twitter API に対応するため最近書き換えた。

今まで実験のため PC の電源を入れているときに気分で動かしていたが、たまに動かすと割と反応をもらえることもあり、継続的に動いてもらうべく常時電源の入っている環境で動かすことにした。

Heroku で動いてもらうことも考えたが、主に Web アプリケーションのためのサービスより手元の環境でゴリゴリやったほうが早いだろうと思ってたまたま持っている Raspberry Pi 3 で動かすことにする。Raspberry Pi 3 は無線LAN設定済み。

rbenv のインストール

とにもかくにも apt-get で入る Ruby が古いので rbenv で新しい Ruby を入れるところから始めよう。rbenv の README に従ってインストールするとすんなり入る。

$ git clone https://github.com/rbenv/rbenv.git ~/.rbenv
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(rbenv init -)"' >> ~/.bashrc
$ ~/.rbenv/bin/rbenv init

# csh や zsh における rehash と同義
$ hash -r

ここで bash を再起動しないと rehash がうまくいかなかった。

ruby-build を入れる

これは rbenv install するために必要。

$ mkdir -p "$(rbenv root)"/plugins
$ git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build

Ruby 2.5.3 のインストール

最新の安定板は 2.6.1 だが、後述の Bundler に不具合があるそうなので一つ前の 2.5.3 を入れる。インストールには20分程度かかった。

# Ruby のビルドに必要
$ sudo apt-get install ruby-dev

# このライブラリも必要だった
$ sudo apt-get install libssl-dev libreadline-dev libsqlite3-dev

$ rbenv install 2.5.3

Bundler の使用

Bundler は npm のように gem パッケージをローカルにインストールするためのパッケージ。鸚鵡ちゃんを今どきの、プロジェクトごとにパッケージを入れる形にして他の人にも使いやすくする。

Gem を使ってインストールする。

$ rbenv exec gem install bundler
$ rbenv rehash

プロジェクトで使うには、そのディレクトリへ移動し次のコマンドを実行する。

$ cd ~/2236om
$ rbenv exec bundle init

するとそのディレクトリに Gemfile というファイルができるので、インストールしたいパッケージを記述していく。

gem 'pit', '0.0.7'
gem 'twitter', '6.2.0'
gem 'sqlite3', '1.4.0'

Gemfile が用意できたら Bundler を使って実際にインストールする。

$ rbenv exec bundle install --path=vendor/bundle

プログラムからは次のように通常の require の前に bundler を追加する。

require 'bundler/setup'

Cron の設定

鸚鵡ちゃんを cron で動かすため which コマンドで ruby の場所を調べて次のような crontab を書いたがうまくいかない。

MAILTO=""
* * * * * /home/pi/.rbenv/shims/ruby /home/pi/2236om/scheduled.rb

次のように cron のログを出力できるようにして調べて見る。

# cron の行のコメントを外す
$ sudo vi /etc/rsyslog.conf
$ sudo /etc/init.d/rsyslog restart

# すべてのログを出力するようにする: EXTRA_OPTS="-L 15"
$ sudo vi /etc/default/cron
$ sudo /etc/init.d/cron restart

# ログを監視
$ tail -f /var/log/cron.log

ログを見ると Ruby 自体は動くようだが、次のようなログが出力され鸚鵡ちゃんだけ動かない。

Mar 10 11:52:02 raspberrypi CRON[8105]: (CRON) error (grandchild #8109 failed with exit status 1)

どうやら実行ディレクトリが怪しいのでホームディレクトリに移動して鸚鵡ちゃんを起動してみる。

$ cd ~
$ ruby 2236om/scheduled.rb
Traceback (most recent call last):
	2: from 2236om/scheduled.rb:16:in `<main>'
	1: from /home/pi/.rbenv/versions/2.5.3/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
/home/pi/.rbenv/versions/2.5.3/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require': cannot load such file -- twitter (LoadError)

ということで実行ディレクトリに原因があるので次のように crontab を書き直す。

MAILTO=""
* * * * * cd /home/pi/2236om; /home/pi/.rbenv/shims/ruby scheduled.rb

これでめでたく鸚鵡ちゃんを動かすことができた。

おまけ:apt-get チートシート

やりたいこと コマンド
パッケージリストの更新 sudo apt update
インストール済みは? sudo dpkg -l
パッケージを検索(完全一致) sudo apt list
パッケージを検索(部分一致) sudo apt search
パッケージをインストール/更新 sudo apt install パッケージ名
パッケージを全て更新 sudo apt upgrade

おまけ:鸚鵡ちゃんが利用している Twitter API のレート制限

API Requests/Window Window
GET statuses/home_timeline 15 15 分
GET statuses/mentions_timeline 75 15 分
POST statuses/update 300 3 時間

タブでもスペースでもインデント幅を自分好みに固定できる Atom パッケージ

どんなコーディングスタイルでもインデント幅を自分好みに固定できる Atom パッケージ fixed-indentation-width を公開した。Atom からインストールできる。

ファイルが 2 spaces だろうが 4 spaces, 5spaces それからハードタブ、どんなスタイルでも自分の決めたインデント幅にできる。

使用するにあたっては Atom がそのコードのインデント幅を知っている必要がある。具体的には EditorConfig などを使って、コードのインデント幅とエディタが想定しているインデント幅を揃えておく必要がある。

リポジトリはこちら。

経緯

どこの誰が広めたのか知らないが、「環境によって見え方が変わるから」「patch でハードタブを扱えないから」「ターミナルからコピペするとタブ文字がスペースになってしまうから」などという的外れな理由で、 Web 業界ではインデントにスペース2つが当たり前になっている。

環境によって見え方が変わるのは、フォントによってスペースの幅が違うからスペースだって同じだし、いまどきの patch はタブをちゃんと扱えるし、そもそもターミナルからコピペすんなよと言いたいところだが、今は prettier だって使えるし問題ない。

現時点での最大の問題は、指定数のスペースしか許さんとぬかしている輩のせいで、ユーザがそれぞれ見やすいインデント幅に設定できないことだ。特にプロポーショナルフォントで表示するとスペース2つなんて漢字一文字よりも狭いからインデントしているんだかしていないんだかはっきりしてほしい状態になる。

しかもだ、一般人が GoogleAirbnb の使っているコーディングスタイルがクールだと言って真似する。そうすると自力で prettier をセットアップできない一般人は悲しいことに、スペースを1つだけ削ったり余計に足したりしてインデントをガタガタに崩してしまう。

一方タブでインデントを行えば、現在使われているほとんど全てのエディタはタブの幅を設定する機能があるので、ファイルのバイト列は変えずに各個好みのインデント幅に設定できる。スペースと違って目立つので一般人にも優しい。

とはいうものの宗教だとか政治の世界になってしまうので、何とか解決するものはないかと Atom をいじくり回してできたのがこのパッケージ。

既知の問題

  • 2段以上のインデントの中間にカーソルを移動させるとカーソルが見えなくなる
  • 起動直後はインデント幅がちゃんと設定されない(内容を変更すると直る)

解決手段を思いついた方は教えてください。