JXAでMacのリマインダーからMarkdownのタスクリストを出力

Markdownのタスクリストについてはこちら

- [Task Lists in GFM: Issues/Pulls, Comments](https://github.com/blog/1375%0A-task-lists-in-gfm-issues-pulls-comments)

# タスク(Reminder)から参照できる情報

タスク(Reminder)はタスクリスト(List)の中に入っている。
タスクリストはApplicationから取得できる。

```js:例
var app = Application("Reminders");
//var allTaskLists = app.lists(); //全タスクリストの配列
var taskList = app.defaultList(); //デフォルトのタスクリストだけ
var tasks = taskList.reminders();
var task = tasks[0];

var taskProperties = task.properties();
//=> {"dueDate":null, "modificationDate":Thu Feb 26 2015 16:50:45 GMT+0900 (JST), "pcls":"reminder", "body":null, "completed":false, "id":"x-apple-reminder://5C688A9A-330B-43A3-89F2-C939883A3544", "creationDate":Thu Feb 26 2015 16:50:45 GMT+0900 (JST), "name":"サンプル", "completionDate":null, "container":Application("Reminders").lists.byId("D361C8C1-EA78-4A07-B5C7-56F4276B9319"), "priority":0, "remindMeDate":null}
```
Accountもあるけどそれは気にしなくてもapp.lists()でリスト全部参照できるはず
アカウント1つしかないので分からない

## タスクのプロパティ一覧

用語説明から引用

###読み書き可能　

- 名前 name (text) : the name of the reminder
- 完了済みか否か completed (boolean) : Is the reminder completed?
- 完了日時 completionDate (date) : the completion date of the reminder
- 期日(↓と同じ？) dueDate (date) : the due date of the reminder
- 通知日時(↑と同じ？) remindMeDate (date) : the remind date of the reminder
- 優先度 priority (integer) : the priority of the reminder
- メモ欄 body (text) : the notes attached to the reminder

dueDateを変更するとremindMeDateも変更される。逆も然り。
違いが分からないけど、他のアプリとかからインポートするときとかの互換のため？
分からん。

### 読み取り専用

- ID id (text, r/o) : the unique identifier of the reminder
- 所属してるタスクリスト container (List, r/o) : the container of the reminder
- 作成日時 creationDate (date, r/o) : the creation date of the reminder
- 変更日時 modificationDate (date, r/o) : the modification date of the reminder

スクリプトからいじれるのはこれだけ。
アプリケーションからは繰り返しと場所の設定もできる。

# ソース

(なぜかScript Editorで実行すると落ちる...?)

```js:RemindersToMarkdown.js
// 表示設定
const INCOMPLETE_ONLY = false; // 未完了のタスクだけ表示するか
const PRINT_OPTIONS = true; // 名前とチェックボックス以外も表示するか (今のとこ優先度, 期日だけ)

// タスクリスト絞り込み (指定しなければ全部表示)
const DEFAULT_LIST = false; // デフォのタスクリストだけ表示するか
const LIST_NAME = null; // 特定のタスクリスト名を指定 (DEFAULT_LISTがtrueなら無効)

function taskInfo(task){ // タスク1つ分の文字列を作成
  // タスクの全プロパティを取得
  var props = task.properties();

  // 名前と完了・未完了は必須
  var name = props.name;
  var completed = props.completed ? "x" : " ";

  var info = "- [" + completed + "] " + name;

  // 付加情報
  if(PRINT_OPTIONS) info += options(props);

  return info;
}

function options(props){ // タスクの付加情報の文字列を作成
  // 期日 (通知日時)
  // dueDateとremindMeDateは同じっぽい。どっちか変更したらどっちも変更される。
  var due = props.dueDate;

  // 優先度
  // デフォ値だけ用意した。スクリプトからはこれ以外の数値も設定しようと思えばできる
  //「None:0, High:1〜4, Middle:5, Low:6以上」という謎仕様
  var priority = {1:"★★★", 5:"★★", 9:"★"}[props.priority];

  // メモ欄
  // とりあえず取得してるけど表示方法が思いつかないから保留
  var body = props.body;

  // 戻り値を作成
  var ret = "";
  if(priority) ret += " " + priority;
  if(due) ret += " [" + due.toLocaleString().match(/\S+/) + "]";
  return ret;
}

function printTask(task){ // タスクを1つプリント
  console.log(taskInfo(task));
}

function printTasks(list){ //タスクリスト内のタスクを全てプリント
  var tasks;

  if (INCOMPLETE_ONLY){
    tasks = list.reminders.whose({completed: false})();
  } else {
    tasks = list.reminders();
  }

  if (tasks.length > 0) {
    if (!DEFAULT_LIST) console.log("\n# " + list.name());
    tasks.map(printTask);
  };
}

function run(){
  var app = Application("Reminders");

  var lists;

  if (DEFAULT_LIST){
    lists = [app.defaultList()];
  } else if (LIST_NAME) {
    lists = [app.lists[LIST_NAME]];
  } else {
    lists = app.lists();
  }

  lists.forEach(printTasks);
}
```

チェックボックスとタスク名を出力したかっただけ。

## 実行結果

リマインダーがこんな感じのときに`osascript`コマンドで実行すると

![スクリーンショット 2015-02-26 6.55.20.png](https://qiita-image-store.s3.amazonaws.com/0/18902/05631b1b-537b-9e8f-f09d-2486f983a4bc.png "スクリーンショット 2015-02-26 6.55.20.png")

こう出力される。

```
# りすと (デフォ)
- [x] 終わったたすく
- [ ] 終わってないたすく
- [ ] 期日がせまってるたすく [2015年2月26日]
- [ ] かなり重要なたすく ★★★
- [ ] わりと重要かもしれないたすく ★★
- [ ] けっこうどうでもいいたすく ★

# りすと2
- [ ] 「りすと2」にあるたすく(1)
- [ ] 「りすと2」にあるたすく(2)
```

このMarkdownをQiitaにそのまま表示させてみるとこう。

># りすと (デフォ)
- [x] 終わったたすく
- [ ] 終わってないたすく
- [ ] 期日がせまってるたすく [2015年2月26日]
- [ ] かなり重要なたすく ★★★
- [ ] わりと重要かもしれないたすく ★★
- [ ] けっこうどうでもいいたすく ★
>
# りすと2
- [ ] 「りすと2」にあるたすく(1)
- [ ] 「りすと2」にあるたすく(2)

Markdownを読み込んでタスクを作成したり、編集結果をタスクに反映みたいなこともしたかったけど保留
JXAでテストする方法分からなくてあんまりめんどくさいスクリプト作る気しない
テストどうすればいいんだ...
誰か教えてください
あとJXAのLibraryってなんか動かない

# おまけ: 完了済みタスクを消去

上の作ってたら完了済みのタスクを一気に消すスクリプトもほしくなったので。
消す前に確認とかしないで消すので注意。

```js:DeleteCompletedTasks.js
var completed = Application("Reminders").lists.reminders.whose({completed:true});

var amount = completed.length;
console.log("  completed tasks: " + amount);

if (amount) {
  tasks = completed().reduce(function(a, b){return a.concat(b)});
  tasks.forEach(function(task, i){
    console.log("    [" + (i + 1) + "]" + " deleting... " + task.name());
    task.delete();
  });
};
```