| @Mac/iPhone

Fire

Memolist.vim の保存先を Dropbox にする運用を長年続けてきたが、 iOS の Markdown エディターの iA Writer で編集時にファイルが無限複製されるという問題があることや、最近のポリシー変更で Dropbox を無料で使い続けるのは難しそうかつお金を払うにしてもプランが高め(最安でも ¥1,500 / 月で 2TB まで使えるプランしかない)で個人では使いづらそうなので iCloud Drive を代わりに使ってみることにした。 iCloud は今のところ無料で使ってるが 50GB 使えるプランでも月額 ¥130 なので個人で使いやすい。 iCloud Drive は Windows や Linux からは使えないが、 Linux デスクトップはもう何年も使ってないし、 Mac と iPhone にロックインされた生活に不満はないので無問題。

移行の手始めにまずは iCloud Drive にターミナルでアクセスしようとするが、 cd ~/iCloud\ Drive などではたどり着けない。以下の記事を読んで調べた。

パスは ~/Library/Mobile\ Documents/com~apple~CloudDocs で良いみたい。

~/Dropbox/memolist ディレクトリを ~/Library/Mobile\ Documents/com~apple~CloudDocs/Documents/ ディレクトリに移し、 .vimrc を以下のように書き換えた。

diff --git .vimrc .vimrc
index 6c4987e..56882b2 100644
--- .vimrc
+++ .vimrc
@@ -568,7 +568,7 @@

     " memolist.vim {{{

-      let g:memolist_path = "~/Dropbox/memolist"
+      let g:memolist_path = "~/Library/Mobile Documents/com~apple~CloudDocs/Documents/memolist"
       let g:memolist_unite = 1
       let g:memolist_unite_source = "file"
       let g:memolist_unite_option = "-auto-preview -start-insert"

これで Memolist.vim の Markdown ファイル保存先を iCloud Drive に移行できた。

| @技術/プログラミング

@glidenote 先生作の memolist.vim 便利で、仕事のドキュメントからメモ書き、ポエムに至るまで memolist.vim で書いてるけど、 ~/Dropbox/memolist/ にドキュメントが溜まりまくって厳しい感じになってきてた。文章を書く、ということに関しては vim + memolist.vim はとても良いのだけど、書いたものを後から読み直す、という面では弱い部分があると感じる。 iPhone で読みづらいし。その点、 Day One は過去記事を読みやすいし、 iPhone アプリもあるので夜寝る前に過去に書いた文章を読んでニヤニヤしながら眠ることも出来る[1]。

というわけで ~/Dropbox/memolist/ にある Markdown のファイルを Day One.app ( Day One 2)に取り込むやつを書いた。

タイトルにマッチする文字列が入ったファイルを除外したり、その日以降のやつだけ、という感じで絞り込み指定したりできる。めっちゃ便利。

使い方

rb-dayonejson gem が必要なのでインストールしてください。 --execute オプションを付けないとデフォルトは dry-run です。

Example) 今日書いた記事をインポートする

ruby memolist2dayone.rb

Example) 2015/01/01 以降の記事を取り込むが、「日報」という文字列をタイトルに含む記事は除外する

ruby memolist2dayone.rb --since 2015/01/01 --exclude 日報

Example) ~/Dropbox/memolist 以外のディレクトリを対象ディレクトリにしたいとき

ruby memolist2dayone.rb --target_dir ~/memolist/
require 'rb-dayone'
require 'optparse'
require 'json'
dry_run = true
journal_location = "#{ENV['HOME']}/Library/Group Containers/5U8NS4GX82.dayoneapp2/Data/Auto Import/Default Journal.dayone"
target_dir = "#{ENV['HOME']}/Dropbox/memolist/"
since = Date.today
exclude = nil
options = OptionParser.new
options.on('--execute') {|v|
dry_run = false
}
options.on('-j', '--journal VALUE') {|v|
journal_location = v if v != '' || !v.nil?
}
options.on('-t', '--target_dir VALUE') {|v|
if v != '' || !v.nil?
dir = File.expand_path(v)
target_dir = dir if File.exist?(dir)
end
}
options.on('-s', '--since VALUE') {|v|
if v != '' || !v.nil?
since = Date.parse(v)
end
}
options.on('--exclude VALUE') {|v|
if v != '' || !v.nil?
exclude = Regexp.new(v)
end
}
options.parse!(ARGV)
DayOne::journal_location = journal_location
files = Dir.glob(%{#{target_dir}/*\.{markdown,md}})
files = files.grep_v(exclude) if exclude
files = files.delete_if {|file| File.birthtime(file) < since.to_time }
puts "Begin Importing memolist"
puts "Dry run: #{dry_run}"
puts "Target dir: #{target_dir}"
puts "Target files count: #{files.count}"
puts "Journal location: #{journal_location}"
files.each do |file|
content = File.read(file)
if content.nil?
puts "Skip #{file} because content is blank"
next
end
if content.match(/==========/) # memolist defualt
content.sub!(/==========\n/, '')
meta_info, body = content.split('- - -').map {|item| item.strip }
elsif content.match(/\-{3}/) # yaml front-matter
_, meta_info, body = content.split('---').map {|item| item.strip }
else
meta_info = nil
body = content.strip
end
if body.nil? || body.length.zero?
puts "Skip #{file} because body is blank"
next
end
if !meta_info.nil?
meta_array = meta_info.split("\n")
title = meta_array[0].sub(/title: (.+)/, '\\1')
date = Time.parse(meta_array[1].sub(/date: (.+)/, '\\1'))
tags = begin
tags = meta_array[2]
matched = tags.match(/tags: (.*)/)[1]
JSON.parse(matched)
rescue JSON::ParserError
matched.sub(/^\[(.+)\]/, '\\1').split(/,\s/)
end
else
title = File.basename(file).sub(/\d{4}\-\d{2}\-\d{2}\-(.+)?\.(?:.+)$/) { $1 }.gsub(/\-/, ' ').upcase
date = File.birthtime(file)
tags = []
end
unified_body = if body.split("\n")[0].match(/^(?:#\s)?#{title}$/)
body
else
"# #{title}\n\n#{body}"
end
tags << 'from memolist'
entry = DayOne::Entry.new(unified_body, creation_date: date, tags: tags)
if dry_run
puts "#{date} #{title} #{tags}"
else
begin
entry.create!
puts "Successfully save #{date} #{title} #{tags}"
rescue => e
puts e.message
puts e.backtrace.join("\n")
end
end
end

[1]: 前も似たような記事書いてる。 昔の日記を全部 Day One.app にぶっ込んだ - portal shit!

| @技術/プログラミング

memolist.vim のデフォルトのテンプレートが挿入する YAML Frontmatter なんか変わってて、 Jekyll のと違った。 Markdown のプレビューは Marked 2 で見るようにしてるんだけど、 Marked 2 は memolist の特殊 YAML Frontmatter を正しく処理してくれない。 YAML Frontmatter はメタ情報なのでプレビュー時には表示して欲しくない( Marked 2 には YAML Frontmatter を表示しないオプションがある)んだけど必ず表示されてしまう。具体的にはこうなる。

調べてみたら memolist には標準のテンプレート以外に自分の好きなテンプレートを設定できる機能あったので、 ~/.vim/template/memolist/markdown.txt というファイル置いて以下のようにしておいた。なお memolist はテンプレート用ディレクトリに置いてある 拡張子.txt というファイルをテンプレートして利用するようだった。なので Markdown 用のテンプレートは markdown.txt となる。

---
title: {{_title_}}
date: {{_date_}}
tags: [{{_tags_}}]
categories: [{{_categories_}}]
---

テンプレートを変更した上で Marked 2 で YAML Frontmatter を Ignore するよう設定する。

すると以下のような表示になる。すっきりする。

すでに過去に書いた記事の YAML Frontmatter も Jekyll のやつに直す雑なスクリプト書いて直しておいた。

files = Dir.glob("#{ENV['HOME']}/Dropbox/memolist/*.markdown")
files.each_with_index do |file, index|
  filename = File.basename(file)
  filepath = File.expand_path(file)
  flag = true

  lines = File.readlines(file)
  lines[0..5].each_with_index do |line, i|
    case
    when line =~ /^title:(.+)/
      lines[i] = "---\n#{line}"
    when line == "==========\n"
      lines[i] = nil
    when line =~/^(?:date|tags|categories|tags):/
      # do nothing
    when line == "- - -\n"
      lines[i] = line.gsub(' ', '')
    else
      flag = false
      next
    end
  end

  if flag
    p filename
    File.write(filepath, lines.compact.join(""))
  end
end