Automator を使ってテキストを整形する

　Mail.app などで文章を作成するときに便利な Automator ワークフローを作成し、キーボードショートカットに登録して使用しているので、作り方を記す。

### やりたいこと
　メールを書いているときに、見やすいように１行の字数を揃えたり、改行を削除したり、テキストで線を引いたりしたい時がある。これは、Automator のクイックアクションを使えば簡単に実現できる。
　Mac を買い替えた時などに再設定する時どうやればいいか忘れてしまうことがあるので、備忘録として記す。

↓こんな感じ。
<center><img width="600" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/516853/67d8c7e3-9f9e-78e3-7478-3e9f7b136dd0.png" border="1"></center>

### クイックアクションの作り方

　Automator で［新規］メニューを選択すると作成する書類の種類を聞かれるので、歯車アイコンの「クイックアクション」を選択する。

##### （１）アクションをドラッグ
　左側のリストから「AppleScriptを実行」アクションを右側のウィンドウにドラッグ＆ドロップすると、AppleScriptの雛形が作成されるので、ここにコードを入力する。

##### （２）ウィンドウ上部のパラメーターの設定
　パラメーターは以下の通り。

+ ワークフローが受け取る現在の項目：テキスト
+ 検索対象：すべてのアプリケーション
+ 選択されたテキストを出力で置き換える：チェック


##### （３）ワークフローを保存する
　保存する際「クイックアクションの名前」を設定する。
　ここでは［Line］［Justify］［RemoveCR］３つのワークフローを作成する。キーボードショートカットを設定するのに便利なように、名前の出だしを統一すると良い。例えばこんな感じ。

+ Text-Line
+ Text-Justify
+ Text-RemoveCR

　これでワークフローがサービスメニューに登録される。テキストを選択し、［サービス］メニューを選ぶと（メニューバーのアプリケーション名をクリックするか、選択したテキストの上で右クリック）これらのメニューが表示される。
　これだけでも良いが、頻繁に使う機能なので、キーボードショートカットに登録するとさらに便利である。

##### （４）キーボードショートカットの登録
　システム環境設定の［キーボード］をクリックし、左側の［サービス］を選択すると、上記で保存したショートカットが右側に表示される。ショートカットをクリックすると、［ショートカットを追加］というボタンが表示されるので、クリックして他と被らないように覚えやすいキー（例えば、Shift + Option + Command + L）をタイプする。これで、キーボードからサービスメニューを実行できるようになる。

### AppleScriptコード

##### （１）文字で線を引く（Text-Line）
　少し長いメールを書いている時、見やすくするため線で区切りたいことがあるが、これを一発で実現するために作成した。線の長さは text_width で設定している。
　例えば、マイナス記号［-］で線を引きたい場合、［-］を入力して選択状態にして、Text-Lineサービスを実行すると、マイナス記号30文字に置き換わる。［--］にすると、２倍の長さの線が引ける。

```applescript
on run {input, parameters}
	
	set textWidth to 30
	set theLine to ""
	
	repeat textWidth times
		set theLine to theLine & input
	end repeat
	
	return theLine
end run
```

##### （１）１行の文字数を揃える（Text-Justify）
　スマホなどの小型デバイスの場合は改行されない方が読みやすいかもしれないが、ＰＣのメールのようにある程度横幅がある画面の場合は、適度な幅で改行されている方が読みやすい。意味の区切りで改行する人もいるが、私は行末がデコボコするのがイヤなので、１行の文字数をだいたい揃えている。同じように、どのメールも同じ字数にしたいという几帳面な方にオススメしたい。
~~※面倒なので半角文字を0.5とカウントするような処理はしていない。悪しからず。~~
~~※禁則処理はしていない。悪しからず。~~

2019/10/21 追記
選択範囲の文字数が１行の文字数の倍数だった場合にエラーが出るため、一部修正した。
2019/10/22 追記
半角文字（ASCII文字）を0.5とカウントする処理を追加した。
半角カナには対応していない。
簡単な行頭禁則処理にも対応した。

```applescript
on run {input, parameters}
	
	set CR to ASCII character 13
	set textWidth to 30

	set inputText to input as string
	set l to length of inputText

	set outputStrings to ""
	set hnkCount to 0
	set knsCount to 0

	repeat with i from 1 to l
	
		set aStr to text i of inputText
		if isHNK(aStr) = true then
			set hnkCount to hnkCount + 1
		end if
	
		set outputStrings to outputStrings & aStr

--行末の場合、改行を追加
		if ((i - (hnkCount div 2) - knsCount) mod textWidth) = 0 then
			set outputStrings to outputStrings & CR
		end if
--行頭が禁則文字の場合、改行を削除して禁則文字と改行を追加する	
		if ((i - (hnkCount div 2) - knsCount) mod textWidth) = 1 and isKNS(aStr) = true then
			set knsCount to knsCount + 1
			set outputStrings to text 1 thru -3 of outputStrings & aStr & CR
		end if
	
	end repeat
	
	return outputStrings
end run


on isHNK(aStr)
	
	if id of aStr is not greater than 256 then
		set HNK to true
	else
		set HNK to false
	end if
	
	return HNK
	
end isHNK

on isKNS(aStr)
	
	-- 行頭禁則文字列
	set knsStrings to "),.?]}、。，．）］｝】・"
	
	if knsStrings contains aStr then
		set KNS to true
	else
		set KNS to false
	end if
	
	return KNS
	
end isKNS
```

##### （１）改行を削除（Text-RemoveCR）
　文字数を揃える前に、すでに改行されたテキストの改行マークを削除したい場合もある。そこで、改行を削除するショートカットがあると便利である。

```applescript
on run {input, parameters}
	
	set inputText to input as string
	set oldDelim to AppleScript's text item delimiters
	
	set AppleScript's text item delimiters to "\n"
	set aList to text items of inputText
	set AppleScript's text item delimiters to ""
	set inputText to aList as string

	set AppleScript's text item delimiters to oldDelim

	return inputText
end run
```

### 参考資料
　以下の資料を参考にしました。
AppleScript 全般。文字列の扱いなど。
長野谷隆昌@Piyomaru Software 著『AppleScript 最新リファレンス』
https://piyomarusoft.booth.pm/items/307646
http://piyocast.com/as/

バッククォートの入力方法
https://qiita.com/naoyukisugi/items/2f51bc232d1a9ae28df6

　他にも参考にしたかもしれませんが、記録していなかったので分からなくなりました。参考にしたサイトのオーナーのみなさますみません。