todoリストをwebに公開した話

自分が開発したいこと、勉強したいことをwebに公開した。

naoty.info/todo

以前に書いた記事の通り、ここ数週間vimでtodoリストを書くようになった。これがなかなかよくて、.vimrcをいじってtodoリストを書きやすいようにvimをカスタマイズした。GUIアプリだと自由にカスタマイズできなくて、痒いところに手が届かずに使わなくなってしまうケースがあったけど、vimだと自由にいじれるからそういうこともなく長続きしているのだと思う。

そうこうしてるうちに、vimで書いたtodoリストはどんどん増えていった。その中には誰かがやってくれればいいものもあったので、公開していいかと思った。あと、todoリストを買い物リストのように使うことがあって、そういうときに外出先でiPhoneからチェックしたいと思ったのでwebで公開した。viewportを設定してモバイル端末からも見やすいようにした。

公開の仕組みは単純で、todo.mdというファイルをguardで監視して保存されたら自動的にあるスクリプト(下記リンク)とscpが実行されるようにした。このスクリプトはtodo.mdをパースし用意しておいたテンプレートとくっつけてHTML化する。そして、そのHTMLがscpでサーバーにアップロードされる。

naoty/md2html · GitHub

あとRedcarpetをちょっと拡張して- [ ], - [x]チェックボックスに変換するようにした。これはGithub Flavored Markdownで実装されているTask Listの形式を参考にした。


余談

最初はこの仕組みをSinatra、Heroku、Dropbox APIで作ろうとしたのだけど、いろいろ問題があって今の仕組みにいたった。結局「markdownの変換」「scpによるアップロード」の2つを自動化しただけのシンプルな形になった。最近これ以外にも、仕組みを選択する段階で失敗する経験があった。単純な仕組みであるほど問題は少ないし、起きたときに解決しやすいと思った。

「todoリストをテキストファイルとして扱う」というアイデアは、vimを十二分にカスタマイズ可能なtodoアプリとして扱えるようになっただけでなく、今回のようにtodoリストをwebに公開するというところまで行き着いた。なんかで読んだけど、データをテキストとして保存した方が扱いやすいというのが身にしみて理解できたのでよかった。

vimでTodoリスト

vim

今までいろんなTodo管理アプリを試してきたけど、「GUIアプリほど高機能はいらない」「ターミナル上でtodoを確認したい」という理由でvimでTodoリストを書くようになった。これによるとGithubがGithub Flavored MarkdownにTodoリスト記法を実装したようなので、これに倣ってmarkdownでTodoリストを書くことにした。

todoコマンド

まず、Todoリストを開くコマンドをaliasで定義してみた。これでtodoでTodoリストを確認できる。さらに、Dropbox上にファイルを置けば複数PCで共有できるので、オフィスのPCとプライベートPCでTodoリストを共用できる。

# .zshrc

if [ -e "$HOME/Dropbox" ]; then
  alias todo="$EDITOR $HOME/Dropbox/.todo.md"
else
  alias todo="$EDITOR $HOME/.todo.md"
end

vimでmarkdownを書く準備

次に、vimでmarkdownを書く準備をする。普通に*.mdを開くとmodula2というfiletypeで認識されてしまい、markdownファイルとして見なされないので、便利プラグインをインストールする。

" .vimrc

NeoBundle 'tpope/vim-markdown'

折り返しを有効にする

これだけでも十分なんだけど、より使いやすくするための設定を自分なりに考えてみた。まず、一行が長くなるとリストとしては見づらいので、普段は折り返さないけどmarkdownのときだけ折り返すようにしてみた。

" .vim/ftplugin/markdown.vim

" 折り返しを有効にする
set wrap

" 80文字で折り返す
set textwidth=80

" マルチバイト文字の場合も折り返しを有効にする
set formatoptions+=m

Todoリストを簡単に書く

上でふれたGithubが実装したTodoリスト記法- [ ], - [x]を簡単に入力するための設定も書いた。abbreviateを使うと略記を登録することができる。下の設定ではtl<space>と入力すると- [ ]と自動的に変換される。さらに、Todoリストのある行の上で<Leader>を2回おすと(僕は<Leader><space>にしてる)、チェックをon/off切り替えられる。

" .vim/ftplugin/markdown.vim

" todoリストを簡単に入力する
abbreviate tl - [ ]

" todoリストのon/offを切り替える
nnoremap <buffer> <Leader><Leader> :call ToggleCheckbox()<CR>

function! ToggleCheckbox()
  let l:line = getline('.')
  if l:line =~ '^\-\s\[\s\]'
    let l:result = substitute(l:line, '^-\s\[\s\]', '- [x]', '')
    call setline('.', l:result)
  elseif l:line =~ '^\-\s\[x\]'
    let l:result = substitute(l:line, '^-\s\[x\]', '- [ ]', '')
    call setline('.', l:result)
  end
endfunction

スクリーンショット

普段は下のようにtmuxで画面を分割して小さいウィンドウ(右上)にTodoリストを表示しながら開発している。

f:id:naoty_k:20130428002301p:plain

vimプラグインを作ってみた

vim

はじめてvimプラグインというものを作ってみた。コメントを折りたためるようにするだけ。zm, zrなどで表示/非表示を切り替えられる。NeoBundleでインストールすればそのまま使える。

naoty/vim-folcom · GitHub

金曜日にmrubyの勉強会にいって、build_config.rbの大量のコメント(デフォルト値のコメントアウト)を見てウッとなって、コメントだけ非表示にできないか調べてみたら意外に簡単にできた & 手頃なプラグインがなかったので作ってみた。

コメントって読む人が初心者の場合はとても助かるけど、分かってる人にとっては邪魔なだけだから、コメントを読む人が表示/非表示を切り替えられた方がいいと思った。分かってる人には邪魔だろうなと思ってコメント書かないと初心者は困ってしまうので、読む側がコメントを見るかどうかを判断すればいいと思う。そしたら、コメント書く側は初心者のことを考えてコメントを書くようになるんじゃないかと思う。


参考

vimの便利機能

vim

入力補完

  • インサートモードで<C-n>または<C-p>と打つと、補完候補が出てきます。

バッファ

  • 新しいファイルを開くと、バッファという領域にその中身が読み込まれます。過去に開いたファイルをまた開くときに便利です。
  • 直前に開いたファイルに戻りたい場合によく使います。
  • 個人的には、前後のバッファに移動したりバッファから履歴を削除するために以下のようなマッピングを設定しています。
nnoremap <Tab>     :bnext<CR>
nnoremap <S-Tab>   :bprevious<CR>
nnoremap <Leader>d :bdelete<CR>
  • これでTabやShift+Tabで前後のバッファに移動できます。

タブ

  • vimにもブラウザのようなタブがあります。同時に多くのファイルを開きたいときによく使います。
  • デスクトップPCであまり画面が大きくない場合、分割して複数のファイルを開くよりタブの方が出番が多いような気がします。
  • 個人的には、前後のタブに移動したり新しいタブを開くために以下のようなマッピングを設定しています。
nnoremap <Leader>t :tabnew<CR>
nnoremap <Leader>n :tabnext<CR>
nnoremap <Leader>p :tabprev<CR>

コマンド定義

  • 文字コードを変換したりインデント量を変更する操作はけっこうやるので、自分でコマンドを定義して一発で操作できるようにするとラクですね。
command! Indent2 :setlocal tabstop=2 shiftwidth=2
command! Indent4 :setlocal tabstop=4 shiftwidth=4
command! ToSjis :e ++enc=sjis<CR>
  • これで普通に:Intent2と打てばインデント量が2になります。
  • 基本はcommand! <Command name> <command>です。コマンド名は大文字から始めなくちゃいけないようです。あとはいろいろオプションがあるので、詳しくは:help command-nargsを見てください。

abbreviate

  • abbreviateは長くてめんどくさい表記に略を設定できる機能です。
abbreviate #i #include
  • 例えば上のように設定すると、"#i[space]"と入力すると勝手に"#import[space]"と変換してくれます。あとはコメントブロックを入力するのによく使われるみたいです。
abbreviate #b /****************************
  • abbreviateは応用としてtypoを修正するのにも便利です。"abbreviate"っていう単語がもうtypoしそうですね。あと、個人的に"receive"を"recieve"と書いてしまうことが多いので以下のように設定します。
" abbreviate <誤> <正>
abbreviate abbriviate abbreviate
abbreviate recieve receive
  • abbreviateの設定をそのまま.vimrcに書くと、ハードコーディング感があって個人的に気持ち悪いので、.vim/abbreviate.vimという別ファイルに分けて書いてます。
" .vim/abbreviate.vim
abbreviate abbriviate abbreviate
abbreviate recieve receive

" .vimrc
source ~/.vim/abbreviate.vim

filetype毎の設定ファイル

  • 言語によってインデント量を変えたいってケースはほとんどのvimmerにあると思うんですが、そういうときに僕はfiletype毎の設定ファイルを用意しています。
  • インデント量だけならautocmdを使うのもアリだと思うのですが、上のabbreviateで設定したコメントブロックのように言語によって細かく設定を変えたいケースが地味にあるので、設定ファイルを用意する方法を採っています。
.vim
|- ftdetect
    |- filetype.vim
|- ftplugin
    |- javascript.vim
    |- make.vim
    |- ruby.vim
.vimrc
  • 上のようなディレクトリ構造にしておくと、各filetypeごとに設定ファイルが読み込まれるようになります。詳しくは:help filetype-pluginらへんを見てください。
  • 例えばMakefileを書く場合、インデントはspaceではなくtabしか使えないので、expandtabを無効にしたいところです。そこで、以下のようなファイルを用意します。
" .vim/ftplugin/make.vim
setlocal noexpandtab
setlocal tabstop=8
setlocal shiftwidth=8

filetypeの指定

  • Gemfileなど拡張子では判別できないファイルのfiletypeを指定したい場合、ftdetectが便利です。
.vim
|- ftdetect
    |- filetype.vim
.vimrc
" .vim/ftdetect/filetype.vim

autocmd BufRead,BufNewFile Gemfile    setfiletype ruby
autocmd BufRead,BufNewFile Guardfile  setfiletype ruby
autocmd BufRead,BufNewFile *.rabl     setfiletype ruby
autocmd BufRead,BufNewFile *.jbuilder setfiletype ruby
autocmd BufRead,BufNewFile *.ru       setfiletype ruby
  • 上のように設定ファイルを用意すると、指定したファイルを自動的にrubyをfiletypeとして開いてくれます。

以上の設定はすべて僕のdotfilesに書いてあるので参考にしてみてください。

読み返してみると、その筋の方に怒られそうな気がしてきた…(´・ω・`)

IntelliJ IDEAをvimっぽくする

Androidアプリ開発しててEclipseが重くてつらかったので、IntelliJ IDEAなるものを試してる。見た目がかっこいいからこっち使ってみようと思い、vimっぽく使えるか試してみた。

バージョン

テーマを黒にする

  • こっちの方がイケてる。
  • Preferences > Appearance > ThemeをDarculaに変更する。

f:id:naoty_k:20130104233050p:plain

IdeaVimを追加

  • キーマップをvim化する。
  • Preferences > Plugins > Browse repositories > IdeaVimでダブルクリックするとインストールできる。

f:id:naoty_k:20130104233555p:plain

カーソルがどこまでも右にいける設定をオフにする

  • Preferences > Editor > Allow placement of caret after end of lineをオフにする。

f:id:naoty_k:20130104233620p:plain

行番号を表示する

  • Preferences > Editor > Appearance > Show line numbersをオンにする。

f:id:naoty_k:20130104233646p:plain

キーマッピングをカスタマイズする

  • Preferences > Keymapからいろいろ変更できる。
  • Second Strokeを指定することでPrefixみたいなキーマッピングも設定できる。
  • 変更したのは以下のとおり。これでだいたいvimと同じ動きになる。
  • Run:実行
  • Select Next Tab, Select Previous Tab:タブを前後に移動
  • Recent Files:最近開いたファイルのファイラーを起動(unite.vimっぽく使える)
  • Split Horizontally, Split Vertically:エディタを水平分割、垂直分割
  • Goto Next Splitter, Goto Previous Splitter:分割したエディタを前後に移動
  • Close:エディタを閉じる

f:id:naoty_k:20130104233706p:plain

Eclipseだとタブの移動とか画面分割をショートカットからできなかった気がするので、これだけでもインテリJ氏に替える価値があると思う。作業効率がだいぶ上がる。

Rails開発環境 2012夏

5月に「Rails開発環境 2012初夏」という記事を公開してそこそこ好評だったので、最近導入してLife-Changingだったツールを「2012夏」バージョンとして紹介しようと思います。今回紹介するのは以下の3つです。

  • pow + xip.io
  • tmuxinator
  • ctrlp.vim

1. pow + xip.io

pow + xip.ioによって同じネットワーク内にある、iPhoneiPadのような他のデバイスからローカルサーバーに接続できるようになりました。これは、スマホ用サイトやアプリで使うAPIの開発で非常に重宝します。特に、実機でないと確認できないような場面では、pow + xip.ioがないと、ステージング環境にデプロイする必要が出てきて、非常に面倒です。

インストールは、公式ページにあるように以下のコマンドを入力するだけです。

$ curl get.pow.cx | sh

使い方としては、まず、Railsのプロジェクトルートへのシンボリックリンクを.powディレクトリに作ります。

$ cd ~/.pow
$ ln -s ~/workspace/rails/cui-aboutme

すると、これだけでローカルサーバーが起動して、http://cui-aboutme.devでアクセスできます。簡単ですねー。

$ open http://cui-aboutme.dev

同じLANにあるデバイスからは、プライベートIPアドレスを使ってアクセスすることができます。

$ ifconfig
...
        inet 192.168.1.4
...

ifconfig等で調べた結果、上のようになった場合、http://cui-aboutme.192.168.1.4.xip.ioで他のデバイスからもアクセスできます。

f:id:naoty_k:20120808013751j:plain

注意点としては、Lionでは「システム環境設定」→「共有」→「Web共有」を有効にしておく必要があります。これがオフになっててハマりました…><ちなみに、Mountain Lionでは「Web共有」の項目がなくなっていますが、手元では無事に成功しています。

実際にプロジェクトで使っていく中でのTipsをいくつかご紹介します。

powder

powderはpowの操作をカンタンに行うためのコマンドラインツールです。Gemfileからインストールします。

# Gemfile

group :development do
  gem 'powder'
end

シンボリックリンクを.powに作る操作や、サーバーを再起動する操作などをカンタンなコマンドで実行できます。

$ powder link
$ powder restart

詳細は公式ページを参照してください。

pry-remote

pryを使っている方は多いと思いますが、powのサーバーはrails sで起動するわけではないので、普通のやり方ではpryを使うことができません。そこで活躍するのが、pry-remoteです。これもGemfileからインストールします。

# Gemfile

group :development, :test do
  gem 'pry-rails'
  gem 'pry-remote'
end

使い方は、いつものbinding.pryの代わりにbinding.pry_remoteとコードに追加して、実行すると処理が止まります(見た目には分かりにくいけど…)。そこで、

$ pry-remote

と打つと、いつものpryコンソールに入れます。

ちょっと分かりにくいかもしれませんが、公式ページも見てもらって実際に使うと雰囲気がわかるとおもいます。

2. tmuxinator

tmuxinatorは、tmuxで起動するセッションをあらかじめ定義しておいて、コマンド一発で開発環境を起動することができるツールです。gemで配布されているので、bundlerでインストールします。公式ページにしたがって準備します。

$ gem install tmuxinator
$ echo "[[ -s $HOME/.tmuxinator/scripts/tmuxinator ]] && source $HOME/.tmuxinator/scripts/tmuxinator" >> .zshrc
$ source .zshrc

使い方としては、mux new [project name]でテンプレートを作って、起動するセッションを定義していきます。

$ mux new cui-aboutme
# .tmuxinator/cui-aboutme.yml

project_name: cui-aboutme
project_root: ~/workspace/rails/cui-aboutme
tabs:
  - main:
      layout: tiled
      panes:
        - git fetch --prune && git status --short --branch
        - curl http://cui-about.me/users
        - tig
  - vim: vi
  - app:
      layout: even-horizontal
      panes:
        - rails c
        - tail -f log/development.log
  - test: guard
  • 各項目で、起動時に実行するコマンドを定義しています。
  • tabsで起動するタブ毎の設定を定義します。上の設定例だと、「main」「vim」「app」「test」の4つのタブを起動します。
  • panesでタブ内で分割するペインを定義し、layoutでペインの配置を定義します。上の設定例だと、「main」タブに「git fetch等gitの操作」「curl等シェルの操作」「tigでコミットログのビューワー」の3つのペインを起動します。

その他、いろいろな設定ができるようなので詳しくは公式ページをご覧ください。

3. ctrlp.vim

ctrlp.vimは、Ctrl-pで起動するファイラーです。unite.vimと近いのかもしれませんが、僕はこっちの方がサクサクしてて操作もわかりやすくて好きです。下はスクリーンショットです。

f:id:naoty_k:20120808095402j:plainf:id:naoty_k:20120808100021j:plain

.vimrcで以下のように設定しました。

" .vimrc

Bundle 'kien/ctrlp.vim'

let g:ctrlp_cmd = 'CtrlPMixed'
let g:working_path_mode = 'rc'
let g:custom_ignore = {
  ¥ 'dir': '¥.git¥|vendor/bundle¥|tmp',
  ¥ 'file': '¥.jpg$¥|¥.jpeg$¥|¥.png$¥|¥.gif$¥|¥.log'
  ¥ }
  • Ctrl-pで起動するモードを file + mru + bufferを同時に検索するMixedにしています。これで「現在のディレクトリ以下」「よく使うファイル」「バッファ」の中から検索します。
  • 'rc'モードにすることで、.gitがあるディレクトリを優先するみたいです。
  • vendor/bundleやtmpといったディレクトリや*.logのような大きいファイルを無視することで、起動をスムーズにしています。

その他いろいろ設定があるようなので、ヘルプや公式ページをご覧ください。

さくらVPS作業メモ(rubyインストールまで)

環境

  • さくらVPS 512
  • CentOS
  • naoty@local:ローカルの作業用ユーザー
  • root@sakura:さくらVPSのroot
  • naoty@sakura:さくらVPSの作業用ユーザー
  • 使いまわしてる設定ファイル:https://github.com/naoty/dotfiles ブランチはserver

sshでrootにログイン

naoty@local% ssh-keygen -R xxx.xxx.xxx.xxx
naoty@local% ssh root@xxx.xxx.xxx.xxx

作業用ユーザーの作成

root@sakura% useradd naoty
root@sakura% passwd naoty

su, sudoをwheelのみに限定

root@sakura% usermod -G wheel naoty
root@sakura% visudo
root@sakura% vi /etc/login.defs
root@sakura% exit

公開鍵でのログインに変更

naoty@local% scp .ssh/id_rsa.pub naoty@xxx.xxx.xxx.xxx:~
naoty@local% ssh naoty@xxx.xxx.xxx.xxx
naoty@sakura% mkdir .ssh
naoty@sakura% chmod 700 .ssh
naoty@sakura% mv id_rsa.pub .ssh/authorized_keys
naoty@sakura% chmod 600 .ssh/authorized_keys
naoty@sakura% sudo vi /etc/ssh/sshd_config
naoty@sakura% sudo /etc/init.d/sshd restart
naoty@sakura% exit
naoty@local% ssh sakura

yumでgit, zsh, vimをインストール

naoty@sakura% sudo yum -y update
naoty@sakura% sudo rpm -ivh http://repo.webtatic.com/yum/centos/5/latest.rpm
naoty@sakura% sudo yum -y --enablerepo=webtatic install git zsh vim-enhanced

使い回してる設定ファイルを適用

naoty@sakura% ssh-keygen -t rsa
naoty@sakura% cat .ssh/id_rsa.pub
# githubにsakuraの公開鍵を設定
naoty@sakura% git clone git@github.com:naoty/dotfiles.git
naoty@sakura% cd dotfiles
naoty@sakura% git checkout server
naoty@sakura% cd
naoty@sakura% ln -s dotfiles/.gitconfig ~/.gitconfig
naoty@sakura% ln -s dotfiles/.gitignore_global ~/.gitignore_global
naoty@sakura% ln -s dotfiles/.vimrc ~/.vimrc
naoty@sakura% mkdir -p .vim/colors
naoty@sakura% exit
naoty@local% scp -P sshd .vim/colors/railscasts.vim naoty@xxx.xxx.xxx.xxx:.vim/colors/

パスを通す

naoty@local% ssh sakura
naoty@sakura% vi .bash_profile
naoty@sakura% source .bash_profile

iptablesの設定(とりあえずsshと内部からのコネクションのみ)

naoty@sakura% sudo iptables -A INPUT -p tcp --dport sshd -j ACCEPT
naoty@sakura% sudo iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT
naoty@sakura% sudo iptables -P INPUT DROP
naoty@sakura% sudo /etc/init.d/iptables save
naoty@sakura% sudo /etc/init.d/iptables restart

rvmのインストール

naoty@sakura% cp /etc/pki/tls/certs/ca-bundle.crt .
naoty@sakura% sudo curl http://curl.haxx.se/ca/cacert.pem -o /etc/pki/tls/certs/ca-bundle.crt
naoty@sakura% sudo bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer )
naoty@sakura% su -
root@sakura% usermod -G wheel,rvm naoty
root@sakura% exit
naoty@sakura% exit
naoty@local% ssh sakura

rubyのインストール

naoty@sakura% sudo yum install -y gcc-c++ patch readline readline-devel zlib zlib-devel libyaml-devel libffi-devel openssl-devel make bzip2 autoconf automake libtool bison
naoty@sakura% rvm install 1.9.3
naoty@sakura% rvm use 1.9.3 --default