vimのメモ取り環境
僕は全てのメモを「Gmailで自分宛てに送信」して記録している。 インストールログや便利なツールのメモ、数学のパズル、役所の手続きから買い物リストまで、何もかもをGmailに送信しているのだ。 リマインダもToDoリストも全てメール管理。 閲覧は主にスマホとPCのブラウザで、検索はGmailの検索窓を使っている。
話は変わるが、人生とgitの最大の違いは因果律にあると思う。
人生にタイムマシンは存在せず、git reset --hard
やgit rebase
などの便利コマンドもなく、ひたすらコミットを積み重ねることしかできない。
メモは人生のコミットログであり、その媒体に相応しいのは再編集不可能なメールだと、僕は思う。
EvernoteやSlackを使いこなす意識の高い連中には分かるまい~
だいぶ脱線したが、僕のWindowsのメモ取り環境は以下のような感じ。
コンセプトは「とにかく素早いメモ書き」「原始的」の2点。 後者について補足すると、vimプラグインは一切使わず、vim以外のフリーソフトも一切使わず、Windows謹製の機能だけで手軽なメモ取り環境を作りたい。 ちなみにLinuxやMacだと、msmtp等を使えば原始的なメモ環境の構築など造作も無いので、今回は(厄介な)Windowsに焦点を絞った。
Windowsでvimを即座に起動する
パスの通ったディレクトリにgvim.exeへのショートカットリンクgvim.lnk
を設置すれば、上で書いた
が実現できる。起動時間の短縮には、やはりマウスよりキーボードの方が向いていると思う。
参考:http://www.kamomer.com/entry/windows10-run-filename
gvim.exeの起動は簡単だが、問題はメモ内容をメール送信する部分だ。これを外部ツールに頼らずに実現したい。
vimで書いたメモをSMTPでGmailに送信
まず以下のsendGmail.vbs
というファイルを、:set fenc=cp932で保存する。
このファイルは標準入力を受け取ってメール送信するVBSスクリプト。
Dim objStdIn Dim intExitCode Set objStdIn = Wscript.StdIn Set cdo = Wscript.CreateObject("CDO.Message") With cdo .From = "hoge@gmail.com" .To = "hoge@gmail.com" .Subject = "自分用メモ" .ReplyTo = "hoge@gmail.com" .Textbody = objStdIn.ReadAll .BodyPart.Charset = "Shift-JIS" end With schemas_url ="http://schemas.microsoft.com/cdo/configuration/" With cdo.Configuration.Fields .Item (schemas_url & "sendusing") = 2 .Item (schemas_url & "smtpserver") = "smtp.gmail.com" .Item (schemas_url & "smtpserverport") = 465 .Item (schemas_url & "smtpconnectiontimeout") = 30 .Item (schemas_url & "smtpusessl") = true .Item (schemas_url & "smtpauthenticate") = true .Item (schemas_url & "sendusername") = "hoge@gmail.com" .Item (schemas_url & "sendpassword") = "パスワード" .Update end With cdo.Send
再度注意するが、sendGmail.vbsは:set fenc=cp932で保存するように!。 パスワードは平文直書きで、セキュリティコストは自腹。ワイルドだろう?
次に~/.vimrc
に以下を追加
command! Gmail set fenc=cp932 | w !cscript C:/Path/To/sendGmail.vbs " Markdownで書く場合はfiletype切替コマンド(sm)を自作すると便利 nnoremap sm :<C-u>set filetype=MARKDOWN<CR>
以上で設定は終わりだ。
使い方は冒頭で説明したが、vimでメモを書いた後コマンドラインモードで
:Gmail
とすれば、メモがGmailに送信される。めでたしめでたし。
蛇足
メールをUTF-8で送りたかったので、sendGmail.vbs
の
.BodyPart.Charset = "Shift-JIS"
のあたりをいじくり回したのだが、うまくいかなかった。 普通メールの文字コードといえばiso-2022-jpなのだが、windowsでコードを変換するには外部のソフトウェアが必要になる(たぶん)。 少なくとも僕の環境では、vim単体で無名バッファ(UTF-8)をiso-2022-jpに変換することができなかった。 またVBSスクリプトでメールを送信する際も、UTF-8は扱いづらいようだった。
" 変換に失敗する :set fenc=iso-2022-jp :w " うまくいく :set fenc=cp932 :w
文字コードをcp932(Shift-JIS)にしておけば、vimもVBSスクリプトもハマることなく動作した。 やはりWindowsではShift-JISが最強なのだと思いました。
参考
vimをパイプにする
この記事は Vim Advent Calendar 2016 (その2) の3日目の記事です。
ノーマルモード以外をパイプとして使う際の情報を追記しました (2016/12/04)
UNIXのテキスト処理
UNIXでテキストを自動整形する際、パイプ機能は欠かせない。
$ cat a.txt 1 hoge 2 piyo 3 fuga $ cat a.txt |sed 's/piyo/foo/' |grep '2' 2 foo
シェル上で |
というパイプ記号を使ってコマンドを次々繋げることで、複雑なテキスト処理をこなすわけだ。
パイプは便利だが、テキストエディタをパイプとして使う人はあまり見かけない。
テキストエディタ=対話的 という常識があるため、パイプのような自動処理とは相性が悪いと思われているのだろう。
しかし今日はあえて、シェルスクリプトやワンライナーの中にvimを埋め込み、パイプとして静的に使ってみたい。
vimをパイプとして使う
vimを普通に使って冒頭の$ cat a.txt |sed 's/piyo/foo/'
を行うには、ノーマルモードでjwCfoo
と入力すればよい。
このjwCfoo
という呪文をシェル上で使用するには以下のようにすれば良い。
# 最も普通の方法 $ cat a.txt |vim -es +'norm jwCfoo' +%p +q! /dev/stdin # あるいは $ cat a.txt |ex -s +'norm jwCfoo' +%p +q! /dev/stdin # このやり方は Vim: Reading stdin... 問題が生じる $ cat a.txt |vim - -es +'norm jwCfoo' +%p +q! |sed '1d'
とすればよい。一番上のワンライナーの説明をしておくと
vim -e
はex
と等価で、vimを非対話(exモード)で起動するという意味。-s
はサイレントモードで起動し、標準出力を汚さないというオプション。+'norm jwCfoo'
のnorm
は、ノーマルモードのコマンドを使うという意味。jwCfoo
はvimの呪文。中にESCを入れるにはCtrl+vしてESCを押す。+%p
はファイルの全内容を標準出力に表示するexコマンド。+q!
はvimを強制終了するexコマンド。馴染み深い。/dev/stdin
は読み込み先を標準入力 (cat a.txt) にするという意味。
三番目のワンライナーは/dev/stdin
の代わりにハイフン(標準入力のシンボル)を使っていて、スマートに見える。
ただしこの方法では、標準出力の冒頭にVim: Reading from stdin...
というクッソうざい文字列が勝手に挿入される。
こいつを消すには、直後にシェルコマンド|sed '1d'
等を噛ます必要がある。
外部コマンドにしよう
以下のようなvipeコマンドを作っておくと、シェル上でvimの呪文が使いやすくなる。
# .bashrcや.zshrcに書き込む vipe () { COMMAND=$(echo "$*") # コロン':'でESC入力を代替する場合はコメントを外す。^[はCtrl+vしてESC押して入力 # COMMAND=$(echo "$*" |sed -e 's/:/^[/g') vim - -es +":norm gg" +":norm $COMMAND" +:%p +:q! |sed '1d' }
使い方は以下のような感じ。
$ cat a.txt 1 hoge 2 piyo 3 fuga $ cat a.txt |vipe jwCfoo |grep '2' 2 foo # ^[はESC文字で、Ctrl+Vした後にESCを押して入力する $ cat a.txt |vipe Abar^[oxxxx 1 hogebar xxxx 2 piyo 3 fuga # コマンドに空白文字を含む場合は'か"でくくる $ cat a.txt |vipe "A bar baz" 1 hoge bar baz 2 piyo 3 fuga
シェル上でvimのマクロ機能を使う
vimには超便利なマクロ機能が存在する。
簡単に説明すると、ノーマルモードにおける一連の操作をマクロ文字列として記録再生する機能で、
qa
と押すことでレジスタaに記録し、@a
と押すことで再生できる。
上述のjwCfoo
という呪文はvimのマクロの一種といえるだろう。
vimを対話的に使って (qa
を使って) 記録したマクロを表示するには、ノーマルモードで"ap
と押せば良い。
こうして表示されたレジスタaの中身は、vipeコマンドの引数として食わせることが出来る。
$ cat a.txt |vipe "レジスタの中身を書き込む"
これで「vimのマクロを使いまわしたいな〜」なんて場合も安心ですね!
参考
vim -es
とした時に表示されるVim: Reading from stdin...
問題についてはコチラ。
vimのソースコードを修正してくれ~
- http://vi.stackexchange.com/questions/4682/how-can-i-suppress-the-reading-from-stdin-message-from-within-vim
- http://vim.1045645.n5.nabble.com/Vim-Reading-from-stdin-td1151013.html
追記
ブコメで良い指摘をいただきました。
vimをパイプにする - 余白の書きなぐりVimをパイプで使うのめっちゃ便利!ただ、なんでnormalコマンド限定の書き方にしたんだろ?
2016/12/04 01:23
確かに記事中ではパイプの対象をvimのノーマルモードに限定していました。 もしvimのビジュアルモードが使いたければ、以下のようにvを入れれば良いです。
$ cat a.txt 1 hoge 2 piyo 3 fuga $ cat a.txt |vipe lvjhd 1 piyo 3 fuga
矩形選択が使いたければ、vの代わりにCtrl+vを二回連打すれば良いですね。
もしvimのコマンドラインモードを使ってテキストの整形がしたければ...まてよ、vimの親はviでその親はedで、ストリーム版のedはsed... なので、vimの叔父にあたるsedを使うと良いでしょう。
コマンドラインモードを使ったファイルの作成や書き込みは、vipeでむりやり実装するより、シェルのリダイレクション機能を使う方が良いと思います。 「どうしてもvipeでファイルを上書きしたいんやああ」という方がいらっしゃれば、
vim - -es +":norm gg" +":norm $COMMAND" +:%p +:q! |sed '1d'
の:q!
の部分を":wq! hoge.txt"
に変更するなど、うまく調整してください~
apache2でcgiがダウンロードされる時のチェック項目一覧
自鯖のhttp://hogehoge/piyo.cgi
にアクセスしたとき、piyo.cgi
が実行されず、なぜかダウンロードが始まる時のチェック項目一覧
AddHandlerしたか ?
# httpd.conf AddHandler cgi-script .cgi
AddTypeしたか?
# httpd.conf AddType applications/x-httpd-cgi .cgi
OptionでExecCGIしたか?
# httpd.conf Options Indexes FollowSymLinks ExecCGI
a2enmodを有効化したか?
$ sudo a2enmod cgi # Ubuntu14.04LTSの場合
設定終えた後restartしたか?
$ sudo service apache2 restart
cgiのパーミションは大丈夫か?
$ cd /.../cgi-dir/ $ chmod 755 hoge.cgi
cgiを設置したディレクトリのパーミションは?
$ 755 /.../cgi-dir
cgiスクリプトの表示内容は正しいか?
#!/usr/bin/perl print "Content-typo: text/html\n\n"; # タイポしてる!! print "Hello, World.";
他なんかあるかな。 a2enmodの有効化はググってもあんまり出ないし盲点な気がする。
さくらVPSのUbuntu LTS 14.04にSoftether-VPNをインストール
あちこちにインストール方法が書かれてるけど、少しハマったのでメモ。 まずsoftetherのウェブサイトからソースをダウンロードする
$ uname -a # x86_64を確認。64bit用のインストーラーをダウンロードする $ mkdir vpninstall $ cd vpninstall $ wget http://jp.softether-download.com/files/softether/v4.19-9605-beta-2016.03.06-tree/Linux/SoftEther_VPN_Server/64bit_-_Intel_x64_or_AMD64/softether-vpnserver-v4.19-9605-beta-2016.03.06-linux-x64-64bit.tar.gz $ tar xvfz softether-vpnserver-v4.19-9605-beta-2016.03.06-linux-x64-64bit.tar.gz
コンパイルしてインストールする
$ cd vpnserver $ make # 1を三回選んだ $ cd .. $ sudo mv vpnserver /usr/local # make installコマンドは無いようなので、愚直にmvする $ cd /usr/local/vpnserver $ chmod 600 * $ chmod 700 vpncmd vpnserver $ chown root:root * $ chown root:root **/* $ /usr/local/vpnserver/vpncmd # 正しくインストールされてるかチェック
サーバーの電源ON時にvpnserverが自動起動するよう設定
$ sudo vi /etc/init.d/vpnserver $ sudo apt-get install sysv-rc-conf # sys-rc-confはchkconfigのUbuntu版 $ sysv-rc-conf --add vpnserver
/etc/init.d/vpnserver
の中身
#!/bin/sh # chkconfig: 2345 99 01 # description: SoftEther VPN Server DAEMON=/usr/local/vpnserver/vpnserver LOCK=/var/lock/subsys/vpnserver test -x $DAEMON || exit 0 case "$1" in start) $DAEMON start touch $LOCK ;; stop) $DAEMON stop rm $LOCK ;; restart) $DAEMON stop sleep 3 $DAEMON start ;; *) echo "Usage: $0 {start|stop|restart}" exit 1 esac exit 0
管理権限のあるアクセス元IPアドレスをadmini.tmp
に指定。
「管理権限のあるアクセス元のIPアドレス」であり、「クライアントのIPアドレス」ではない。
通常はVPNサーバをインストールしたサーバー自身のIPアドレスを書く。
$ sudo vi /usr/local/vpnserver/adminip.tmp # ファイルには以下のように書く。 192.168.1.2 127.0.0.1
vpnサーバを立ちあげてパスワードを設定
$ sudo /usr/local/vpnserver/vpnserver start # この操作を忘れてハマった $ sudo /usr/local/vpnserver/vpncmd # 何も入力せずエンターを二回押した後、パスワード設定
参考サイト SoftEther VPN Server を CentOS にインストールする 3.5 仮想 HUB のセキュリティ - SoftEther VPN プロジェクト
Windows10でbashが公式サポートされたらしい
Haskellの型推論でハマった話
久しぶりにHaskellで遊んでたらハマったのでメモ。
100の階乗 100!=1*2*...*100
の桁数を求めるプログラムを書いた。
main = print $ kaijo 100 kaijo n = length $ show $ product [1..n] -- 158が表示される。
上記のプログラムは正しい値(158)を返すが、下記のように型を明示すると、誤った値(0)を返す。
main = print $ kaijo 100 kaijo :: Int -> Int kaijo n = length $ show $ product [1..n] -- 0が表示される。なんでや!!
ちなみに100ではなく10の階乗なら、どちらのプログラムも正しい結果を返す。
この不条理の原因は、Intを明示するとproduct
関数の計算がIntで実行されて、
100の階乗という大きな値が桁溢れを起こすせいだと思われる。
Intを明示しなければ、自動で多倍長計算してくれる。
「100を158にする関数」なのに、Int -> Int
とするとバグっちゃう。こわいこわい。
zshのプロンプトを256色にする方法
zshから256色を使う詳細については、以下のサイトの情熱がものすごい。 http://misc.flogisoft.com/bash/tip_colors_and_formatting
しかし肝心のプロンプトの設定方法が載ってなかったので、ここにメモしておこう。
~/.zshrc
で以下のように記述する。
# 例1 # 注意! ^[ は特殊文字。Vim上で Ctrl+Vした後にESCを押せば入力できる。 # 赤(001番)文字+デフォルト背景 PROMPT="%{^[[38;5;001m%}RED%{^[[0m%}"
# 例2 # デフォルト文字色+緑(082番)背景 PROMPT="%{^[[30;48;5;082m%}Green Background%{^[[0m%}"
# 例3 # 赤(001番)文字+緑(082番)背景 PROMPT="%{^[[30;48;5;082m%}%{^[[38;5;001m%}Red on Green Background%{^[[0m%}"
# 例4 # 以下のように文字色を定義しておくと便利 COLOR_FG="%{^[[38;5;001m%}" # 表を赤に COLOR_BG="%{^[[30;48;5;082m%}" # 背景を緑に COLOR_END="%{^[[0m%}" # 色を元に戻す PROMPT="${COLOR_BG}${COLOR_FG}Red on Green Backgroun${COLOR_END}"
ちなみに zshのプロンプトカラーを設定を変更してみた - HAM MEDIA MEMO に書いてある形式
PROMPT=$'%{\e[38;5;46m%}%m%(!.#.$)%{\e[m%} '
ではうまくいかなかった。