" =============================================================== " OreMemo " Web notes (http://espion.s7.xrea.com/) " " $Id: orememo.vim,v 1.11 2004/04/08 06:54:23 gaba Exp $ " =============================================================== " " "LICENCE" " " Copyright (C) 2004 Web notes, All rights reserved " " Redistribution and use in source and binary forms, with or without " modification, are permitted provided that the following conditions are met: " " 1. Redistributions of source code must retain the above copyright notice, " this list of conditions and the following disclaimer. " 2. Redistributions in binary form must reproduce the above copyright notice, " this list of conditions and the following disclaimer in the documentation " and/or other materials provided with the distribution. " 3. The name of the author may not be used to endorse or promote products " derived from this software without specific prior written permission. " " THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED " WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF " MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. " IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, " SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, " PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; " OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, " WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR " OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF " ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. " " ※日本語参考訳 " http://www.jp.freebsd.org/www.freebsd.org/ja/copyright/freebsd-license.html " http://www.jp.netbsd.org/ja/Goals/redistribution.html " " =============================================================== " " "OreMemo とは" " " OreMemo は VIM 上で動作する、分類をメインとしたメモ取り用のプラグインです " " 名前からも想像が出来る通り、自分用に特化したメモ取り環境が " 欲しかったので作りました。 " このため、柔軟性が欠けている部分が多々ありますが、お許し下さい。 " " また、作者は VIM スクリプト初挑戦なので、ヘタレな実装が散見されるかもしれません。 " そんな所を見つけた時は、こっそりと教えて下さいませ。 " " =============================================================== " " "特徴" " " * 保存を意識しないで良い " 文書は自動的に保存されるので、保存のし忘れや不意のシャットダウン " による文書の紛失に悩まなくて済みます。 " " * ChangeLog 形式(他)での保存形式を実装 " メインのメモは ChangeLog 形式で保存し、他は捨てメモに使う、 " 等と言った幅広い(?)使い方が可能です。 " " * 暗号化文書を扱える " パスワード付きファイルを扱う事が出来ます。 " " =============================================================== " " "動作確認済環境" " " ls head grep と、Unix のシステムコマンドを使用しているので、 " Windows 環境で動作させるなら、最低限 Cygwin か perl が必要そうです。 " " VIM が +perl でコンパイルされている環境なら、head と ls コマンドは " 無くても動作します。(:version で確認出来ます) " +perl ならメモ一覧画面の表示と、Grep 検索の結果表示が約2倍の " 速度になるので Windows じゃない人にもオススメ。 " " * Debian/GNU Linux (woody) + VIM 6.1.18 + GNU grep 2.4.2 " * Debian/GNU Linux (sarge) + VIM 6.2.149 + GNU grep 2.5.1 " * Red Hat Linux 7.3 2 + VIM 6.2 + GNU grep 2.4.2 " * Cygwin on WindowsXP + VIM 6.2 + GNU grep 2.5 " " =============================================================== " " "インストール" " " 1: このファイルを runtimepath に含まれるディレクトリに置いて下さい。 " 大抵の場合は ~/.vim/plugin/ 内に置けば平気なはずです。 " " 2: データディレクトリ(初期設定では ~/.orememo/)を作成して下さい。 " 他のディレクトリがいい場合は、後述の「カスタマイズ機能」をご覧下さい。 " " 3: vim を起動して :OreMemo と入力し、Enter を押して下さい。 " それらしい画面が表示されればインストールは成功です。 " " =============================================================== " " "キーバインド" " " デフォルト設定のキーバインドは存在しません。 " 各自 ~/.vimrc 等を使って自由に設定して下さい。 " " 以下は設定の参考例です。 " " * メモ一覧 " nmap o :OreMemo " " * 新規メモ作成 " nmap n :OreMemoNew " " * メモの全文検索 " nmap / :OreMemoSearch " " =============================================================== " " "カスタマイズ機能" " " 以下の値を変更する事により、デフォルトの挙動を変更する事が出来ます。 " 例えば、データディレクトリを ~/newore/ にしたい場合は、.vimrc に " let g:orememo_dir = '~/newore/' " と記述して下さい。 " " * データディレクトリ (Default: ~/.orememo/) " g:orememo_dir " " * タイトルに自動挿入される文字列 (Default: = ) " g:orememo_title " " * 自動プレビュー (Default: 0) " 0:off " 1:on " g:orememo_autopreview " " * 画面分割方式 (Default: 0) " 0:縦分割 " 1:横分割 " 2:なし " g:orememo_splitmode " " * 分割時の大きさ (Default: 20) " g:orememo_splitsize " " * 初期の並び順 (Default: t) " (ls のコマンドラインオプションです) " t: 更新日順 " tr: 更新日逆順 " r: 作成日順 " 1: 作成日逆順 (数字の 1) " g:orememo_sort " " * バッファの保持 (Default: 0) " 0:off " 1:on " g:orememo_buffer " " * 自動保存までの時間 (Default: 200) " g:orememo_updatetime " " * 削除時にバックアップを取らない (Default: 0) " 0:no " 1:yes " g:orememo_backup " " * grep プログラム (Default: grep) " g:orememo_grepprg " " * grep コマンドのオプション (Default: E) " g:orememo_grepopt " " * WWWブラウザ (Default: なし) " g:orememo_wwwprg " " * head コマンドのオプション (Default: v) " g:orememo_headopt " " * 値をセットするとこのプラグインを読み込まない " g:orememo_disable " " * clgrep プログラム (Default: なし) " g:orememo_clgrepprg " " =============================================================== " " "使い方-初級編" " " * はじめに " 上述のキーバインドの項のショートカットの設定をしているとして説明します。 " 設定が違う場合は、自分の設定と置き換えてお読み下さい。 " " * メモを取る " VIM を起動して、 " Ctrl-c n " で新規の 'メモ作成画面' に入ります。 " 1行目がそのメモのタイトルになりますので適切なタイトルを挿入しましょう。 " タイトル分けに興味が無い方のために、デフォルトで日付が挿入されます。 " " * メモの確認 " 今まで書いたメモは " Ctrl-c o " で表示される 'メモ一覧画面' で確認する事が出来ます。 " タイトル上で Enterキー を押すとメモの画面に移動します。 " ? キーを押すとコマンド操作のヘルプが表示されます。 " " * メモの検索 " Ctrl-c / " を押すと grep で全文検索出来ます。 " '検索結果画面' には、タイトルと一致行の一覧が表示されます。 " Enterキー を押せば 'メモ画面' に移動します。 " 一部を除き、操作は 'メモ一覧画面' とほぼ同じです。 " " 検索には正規表現の指定も可能です。 " 例えば検索文字列に a|b とした場合は、 " a もしくは b が含まれるファイルが検出されます。 " " * メモの削除 " 'メモ一覧画面' から削除したいメモの行へ移動し、 " D " を押すと削除の確認メッセージが表示され、OK をすれば削除されます。 " 初期状態では完全に削除されず、データディレクトリ内に 'ファイル名.bak' " という形で保護されますので操作を誤った場合にも安心です。 " もしこのバックアップファイルが不要な場合は、g:orememo_backup を 1 に " セットして下さい。 " " * タイトルのハイライト表示 " 一行目のタイトルの内容により、'メモ一覧画面' において " ハイライト表示させる事が出来るようになっています。 " 具体的にはタイトルの末尾に @ を入れるようにします。 " @ @1 @2 が使用可能です。 " 例えば、「= おれのメモ@」「日記@1」等です。 " " * 特殊な保存形式 (特殊形式) " メモのタイトルを以下の3種類のうちのいずれかにする事により、 " 書式を選択する事が可能です。大文字、小文字の区別はありません。 " 実際にどういう形式かどうかは、ご自分で試してみて下さい。:-) " " [diary] => 日時挿入形式 " [clmemo] => ChangeLog 形式 " [orememo] => orememo 独自形式 " " * ブラウジング機能 " g:orememo_wwwprg を設定しておくと、URL っぽい文字列上で Enterキーを " 押下した場合にそのプログラムで表示しようとします。 " %URL% が実際のURLに置換されます。 " ちなみに作者は " let g:orememo_wwwprg = 'screen w3m "%URL%"' " としています。 " " * サブディレクトリの作成 " データディレクトリ内に、.orememo で終わるような名称(例: sub.orememo 等)で " ディレクトリを作成しておく事により、メモ一覧画面には表示されないが、 " 検索する事が可能なファイルを作成する事が出来ます。 " 主に News Checker (http://espion.s7.xrea.com/dist/news-checker/)との " 連携を意識した機能です。 " " =============================================================== " " "使い方-上級編1:clgrep" " " 高林さんの clgrep のインターフェースを利用する事が出来ます。 " http://namazu.org/~satoru/unimag/1/#label-19 " これを利用すると、特殊形式で保存したファイルに対する検索が便利になります。 " " * 準備 " 上記の clgrep を用意したら、g:orememo_clgrepprg に clgrep " までのパスを設定して下さい。 " let g:orememo_clgrepprg = '/home/foo/bin/clgrep' " 等です。実行権限を付けるのを忘れないで下さい。 " " * 使用方法 " clgrep を実行したいメモを開いてから " :OreMemoClGrep " と入力し、Enter キーを押すと検索文字列の入力を促されるので入力します。 " 結果が表示されれば設定は成功です。 " " * ちょっと便利な使い方 " 通常の grep 検索と異なり、clgrep の場合は検索したいファイルを開いてから " でないと検索する事が出来ません。 " " 特殊形式で保存されているファイルが予め一つと決まっているのならば、 " 引数にファイル名を渡す事により簡単に呼び出す事が可能です。 " " nmap c :OreMemoClGrep('hogehoge') " | hogehoge の部分は検索したいメモの 'ファイル名' になります。 " | ファイル名はディレクトリから手動で探したりして見つけて下さい。 " | 例えば、 20040306153025.orememo みたいな物が入ります。 " | ディレクトリ名は不要です。 " " この設定を行った場合は、Ctrl-c c を押す事により、指定したファイルに対して " いつでも clgrep を行う事が可能です。 " " =============================================================== " " "使い方-上級編2:GPG" " " GnuPG で暗号化したファイルを扱う事が可能です。 " どうしても他人に見られたくないファイルを扱いたい場合に便利です。 " " * GPG の準備 " 当然の事ながら GPG が必要になってきます。 " GPG についての詳しい事は、以下のサイト等で確認して下さい。 " http://www.math.s.chiba-u.ac.jp/~matsu/gpg/ " http://hp.vector.co.jp/authors/VA019487/ " 公開鍵で暗号化しているので、鍵を準備する必要があります。 " 鍵は、 " $ gpg --gen-key " 等とやれば作れると思います。 " " * vimrc の準備 " OreMemo で GPG を使う為には、以下の設定を .vimrc に記述する必要があります。 " " ○1 にすると gpg を使用する。 " let g:orememo_gpg = 1 " ○暗号化で使用する名前(メールアドレス等)。 " 鍵を作成する時に設定した名前やメールアドレスを設定します。 " let g:orememo_gpgrecipient = 'orememo@example.com' " ○パスフレーズを保存するかどうか。 " 1 にしておくと、VIM が起動している間パスフレーズを覚えていてくれます。 " let g:orememo_gpgpassphrase = 1 " ○メモのタイトル一覧。0から順番に好きなタイトルを設定して下さい。 " ※設定例 " let g:orememo_gpglist0 = '[orememo] secret' " let g:orememo_gpglist1 = 'secret memo' " let g:orememo_gpglist2 = '秘密' " " * 使用方法 " 'メモ一覧画面' の末尾に GPG 用のメモ一覧が表示されるので、 " 通常通り Enter で開く事が出来ます。 " 開く際にはパスフレーズの入力を促されるので、入力を行います。 " これらの暗号化されているファイルは、Grep や clgrep の検索は出来ません。 " " 暗号化処理に若干の時間がかかる関係上、定期的な自動保存はされません。 " :w 等で手動で保存する必要があります。 " " * パスフレーズの保存について " ※以下は g:orememo_gpgpassphrase を 1 に設定している方向けです。 " VIM が +perl でコンパイルされて 'いない' 場合は、セキュリティが低下します。 " " ○問題点1: メモを開く際に ps で見るとパスワードが表示される " シェルに直接パスワードを echo させて実行している関係上、 " プロセスにそのまま表示されます。 " $ while : ; do ps aux | grep gpg | grep -v grep ; done " してメモを開いたりすれば確認出来るでしょう。 " ○問題点2: /tmp ディレクトリに一時ファイルを書き出している " 理由が良くわからないのですが、上述の ps で見ると確かに /tmp " に一度ファイルを書き出しているのです。 " これも同じように while して監視していれば、ファイルの中身が簡単に覗けます。 " " 自分一人で使っている環境ならあまり気にならないかもしれませんが、 " 複数の人間がログインしているような環境なら使わない方が無難です。 " これらが原因で大切な情報が漏れたとしても責任は負えません。 " " VIM が +perl でコンパイルされて 'いる' 場合は、これらの心配は無用です。 " ただし、perl 上から GPG へアクセスする為のモジュール(GnuPG.pm)が必要です。 " (Debian なら、libgnupg-perl パッケージ) " 多分ここのやつです → http://indev.insu.com/GnuPG/gnupg.html " " ○共通の問題点: 端末に直接アクセスされるとパスワードがばれる " あなたが起動した VIM をあなたが居ない時(席を外したetc)に " 直接操作出来る人間がいる場合、その人が VIM スクリプトを少し知っていれば、 " 一時的に保持されている情報にアクセス出来るので、パスワードがばれる可能性があります。 " 端末から離れる時は、なるべく VIM を終了させましょう。 " " * その他 " ファイルを削除したくなったら、データディレクトリに「通し番号.oregpg」という " 名称で置いてあるので、それを直接削除して下さい。 " 必要であれば、g:orememo_gpglist も消しましょう。 " " .oregpg という拡張子のファイルを作成すると、自動的に暗号化ファイルとして認識され、 " OreMemo 以外からも扱う事が可能です。 " " =============================================================== " "連絡" " " バグや要望の連絡はサポート掲示板か support@mc.neweb.ne.jp までどうぞ。 " http://espion.s7.xrea.com/tdboard/tdboard.cgi?d=support " " このスクリプトの最新版は、以下のURLから取得出来ると思います。 " http://espion.s7.xrea.com/dist/orememo/ " " =============================================================== " " "FAQ" " " Q: メモ一覧画面上にエラーが表示されちゃうんだけど? " A: もしかしたら、head コマンドがエラーを吐いているかもしれません。 " .vimrc に、let g:orememo_headopt = '' と設定してからもう一度 " 試してみて下さい。 " ただし、この設定を行った場合はメモファイルが1つしか存在しない場合に " 正常に動作しません。 " メモファイルが複数存在すれば問題ありません。 " " Q: ヘルプメッセージが英語なのは何でよ? " A: euc-jp 以外の環境ではメッセージは全て似非英語になります。 " ごめんなさい。よくわからないの。 " " Q: 一覧画面上で Enter 押してもメモ画面に移らないよ? " A: ~/.vimrc が存在しないと発生するようです。 " 空でいいので .vimrc を作成して再度試してみて下さい。 " " =============================================================== " " "TODO" " " * ヘルプの偽英語をなんとかする " " * コード整理 " 再読み込みとか tmp 使う奴がヘコイ気がする " ls 使ってる辺りもヘコイ気がする。 " 検索時に grep 2回実行してるけど1回に出来ない? " " * GPG " パスが漏れるのは何とかならないのか " FileWritePost,BufWritePos 以外でも保存した方がいいのか? " CursorHold で保存したいんだけど、どうすれば... " " * memolist のエラー " バッファリストから無理矢理開いて、もう一度リストを開こうとするとエラーになるっぽい " " * 指定ファイルを直接開けるように " OreMemoOpen(...) にすれば多分OK " " * その他 " 特殊モードの設定 (項目追加、直接開く) " " scriptencoding euc-jp if exists('g:orememo_disable') finish endif "" メモ一覧表示前処理 ------------------------------------------------ function! s:OreMemoMain() let winno = bufwinnr("OreMemoList.orememo") if winno != -1 exe winno.'wincmd w' call s:OreMemoReload() return 0 endif if s:orememosplitmode != '' exe g:orememo_splitsize.s:orememosplitmode.'split' endif call s:OreMemoList() endfun "" メモ一覧画面 ------------------------------------------------------ function! s:OreMemoList() call s:OreMemoEditFile('OreMemoList.orememo', 0, 0) 0put='\" ? : '.s:msg_list_help 1put='\"'.s:msg_list_sort.': '.g:orememo_sort if has('perl') let i = s:OreMemoPerlReadHead() else let i = s:OreMemoReadHead() endif call s:OreMemoGpgList(i) setlocal nomodifiable call s:SetOreMemoCommand() command! -buffer -nargs=1 OMemoReload call s:OreMemoReload() command! -buffer -nargs=1 OMemoToggle call s:OreMemoToggle() nnoremap r :OMemoReload() nnoremap t :OMemoToggle() if has('syntax') syntax match Statement display '^.*@$' syntax match Title display '^.*@1$' syntax match DiffAdd display '^.*@2$' endif endfun "" ファイルを開く ---------------------------------------------------- function! s:OreMemoEditFile(file, mode, search) let num = a:mode == 1 && a:search == 1 ? s:num : 0 exe 'edit ++enc='.&enc.' ++ff='.&ff.' +'.num.' '.a:file silent! setlocal noswf nobackup if a:mode == 1 silent! exe 'setlocal updatetime='.g:orememo_updatetime if g:orememo_buffer == 0 silent! setlocal bufhidden=delete endif if a:file =~ '.oregpg$' silent! setlocal updatetime=9999999 endif else " 一覧、検索モードの場合 silent! setlocal nobuflisted nowrap nonumber bufhidden=delete buftype=nofile updatetime=1000 endif endfun "" ヘルプを表示 ------------------------------------------------------ function! s:OreMemoHelp() echo ' : '.s:msg_list_ret echo ' o : '.s:msg_list_open echo ' O : '.s:msg_list_open2 echo ' p : '.s:msg_list_preview echo ' r : '.s:msg_list_reload echo ' D : '.s:msg_list_delete echo ' t : '.s:msg_list_toggle echo ' q : '.s:msg_list_quit echo '' endfun "" メモを開く -------------------------------------------------------- function! s:OreMemoOpen(mode) let mode = a:mode let file = mode == 1 ? s:OreMemoFindFile(1) : s:OreMemoFindFile(0) if file == '' return 0 endif let line = getline('.') let search = 0 if exists('b:orememobuf') let search = 1 let line = substitute(line, '\v\d+: (.{-}) : .*', '\1', '') endif if mode == 3 silent! only elseif mode == 1 if s:orememosplitmode != '' exe s:orememosplitmode.'new' endif else call s:OreMemoSetWin() endif call s:OreMemoEditFile(file, 1, search) if mode != 1 && line =~? '\[clmemo\]' setlocal filetype=changelog endif call s:SetOreMemoViewCommand() if mode == 1 " New memo call append('0', g:orememo_title.strftime("%y-%m-%d %H:%M")) call append('1', "") call cursor(3, 1) startinsert elseif mode == 2 " Preview if search == 1 if has('syntax') exe 'syntax match Search /^.*\%'.s:num.'l.*$/' endif let winno = bufwinnr("OreMemoSearch.orememo") else let winno = bufwinnr("OreMemoList.orememo") endif if winno != -1 exe winno.'wincmd w' endif elseif mode == -1 elseif line =~? '\[diary\]' " Append date call append('1', "") call append('2', strftime("[%Y-%m-%d %H:%M:%S]")) call append('3', "") call cursor(4, 1) startinsert elseif line =~? '\[orememo\]' " orememo mode let date = strftime("%Y-%m-%d") if strpart(getline(3), 1, 10) == date call append('3', '') call append('4', "* ") else call append('2', '['.date.']') call append('3', '') call append('4', "* ") call append('5', '') endif call cursor(5, 1) startinsert! elseif line =~? '\[clmemo\]' " ChangeLog mode let date = strftime("%Y-%m-%d") if strpart(getline(3), 0, 10) == date call append('3', '') call append('4', "\t* ") else call append('2', date) call append('3', '') call append('4', "\t* ") call append('5', '') endif call cursor(5, 1) startinsert! endif endfun "" 検索前処理 -------------------------------------------------------- function! s:OreMemoSearchPre(file) let s:word = input(s:msg_search_input) if s:word == '' return 0 endif let winno = bufwinnr(a:file) if winno != -1 exe winno.'wincmd w' call s:OreMemoEditFile(a:file.'tmp', 0, 0) else call s:OreMemoSetWin() split silent! exe 'wincmd w' endif let grepopt = g:orememo_grepopt if s:word !~ '\C[A-Z]' let grepopt = grepopt.'i' endif return grepopt endfun "" メモを検索 -------------------------------------------------------- function! s:OreMemoSearch() let grepopt = s:OreMemoSearchPre('OreMemoSearch.orememo') if s:word == '' return 0 endif if grepopt != '' let grepopt = '-'.grepopt endif let grep = grepopt ." '". s:word ."' ". s:orememodir .'*.orememo 2> /dev/null' call s:OreMemoEditFile('OreMemoSearch.orememo', 0, 0) call s:SetOreMemoCommand() let b:orememobuf = 'search' setlocal modifiable call append('0', '" OreMemoSearch ' . s:msg_search_result . ': ' . s:word) if has('perl') call s:OreMemoPerlParseSearch(grep) else call s:OreMemoParseSearch(grep) endif setlocal nomodifiable endfun "" 検索解析処理 ------------------------------------------------------ function! s:OreMemoParseSearch(grep) let grep = a:grep let result = system(g:orememo_grepprg . " -nH " . grep) let head = system(g:orememo_grepprg . " -l " . grep . ' | xargs head -1'.g:orememo_headopt) call s:OreMemoParseHead(head, 1) let i = 1 while result != "" let idx = match(result, "\") let buf = strpart(result, 0, idx) let result = strpart(result, idx+1) let path = substitute(buf, '\v(.{-}/)[^/^:]+.orememo:.*', '\1', '') let file = substitute(buf, '\v.{-}/([^/^:]+).orememo:.*', '\1', '') let line = substitute(buf, '\v.{-}.orememo:(\d+):.*', '\1', '') let msg = substitute(buf, '\v.{-}.orememo:\d+:(.*)', '\1', '') if file == path continue endif let add_line = i.': '.s:orememoline{file}.' : '.msg if match(path, '\v/[^/]+.orememo/$') >= 0 let file = substitute(path, '\v.{-}/([^/]+.orememo/)$', '\1', '').file endif call append('$', add_line) let b:orememofile{i} = file let b:orememonum{i} = line let i = i + 1 endwhile endfun "" clgrep で検索 ----------------------------------------------------- function! s:OreMemoClGrep(...) let file = !exists('a:1') ? expand('%') : a:1 if g:orememo_clgrepprg == '' return 0 endif let grepopt = s:OreMemoSearchPre('OreMemoClGrep.orememo') if s:word == '' return 0 endif if grepopt != '' let grepopt = '-i' endif call s:OreMemoEditFile('OreMemoClGrep.orememo', 0, 0) call s:SetOreMemoViewCommand() call append('0', '" OreMemoClGrep ' . s:msg_search_result . ': ' . s:word) let search = system(g:orememo_clgrepprg.' '.grepopt." '".s:word."' ".s:orememodir.file.' 2> /dev/null') while search != '' let idx = match(search, "\") let buf = strpart(search, 0, idx) let search = strpart(search, idx+1) call append('$', buf) endwhile setlocal nomodifiable endfun "" 再読み込み -------------------------------------------------------- function! s:OreMemoReload() call s:OreMemoEditFile('OreMemoListTmp.orememo', 0, 0) call s:OreMemoList() endfun "" ls オプション切り替え --------------------------------------------- function! s:OreMemoToggle() if g:orememo_sort == 't' let g:orememo_sort = 'tr' elseif g:orememo_sort == 'tr' let g:orememo_sort = 'r' elseif g:orememo_sort == 'r' let g:orememo_sort = '1' elseif g:orememo_sort == '1' let g:orememo_sort = 't' endif call s:OreMemoReload() endfun "" ファイル削除 ------------------------------------------------------ function! s:OreMemoRemove() let file = s:OreMemoFindFile(0) if file == '' return 0 endif if confirm(s:msg_conf_delete) == 1 let retval = g:orememo_backup == 1 ? delete(file) : rename(file, file.'.bak') setlocal modifiable .d setlocal nomodifiable endif endfun "" 終了 -------------------------------------------------------------- function! s:OreMemoQuit() silent! only silent! bw endfun "" ファイル名取得 ---------------------------------------------------- function! s:OreMemoFindFile(mode) let line = getline(".") if a:mode == 1 let file = strftime("%Y-%m-%-d_%H-%M-%S") let file = s:orememodir.file.'.orememo' else if line =~ '^"' || line =~ '^\s*$' return 0 endif let file = strpart(line, 0, match(line, ': ')) if exists('b:orememobuf') let s:num = b:orememonum{file} endif if exists('b:orememosec'.file) let file = s:orememodir.b:orememosec{file} else let file = b:orememofile{file} let file = s:orememodir.file.'.orememo' endif endif return file endfun "" タイトルリスト読み込み -------------------------------------------- function! s:OreMemoReadHead() if system('ls '.s:orememodir.' 2> /dev/null') == '' return 0 endif let head = system('ls -d'.g:orememo_sort.' '.s:orememodir.'*.orememo | xargs head -1'.g:orememo_headopt . ' 2> /dev/null') let num = s:OreMemoParseHead(head, 0) let i = 1 while i < num call append('$', i . ": " . s:orememoline{b:orememofile{i}}) let i = i + 1 endwhile return i endfun "" head 結果解析 ----------------------------------------------------- function! s:OreMemoParseHead(head, mode) let head = a:head let head = a:mode == 0 ? substitute(head, '==> \(.\{-\}\).orememo <=='."\", '\1: ', 'g') : substitute(head, '==> [^ ]*/\([^\/]\+\).orememo <=='."\", '\1: ', 'g') let head = substitute(head, "\\", "\", 'g') let i = 1 while head != "" let idx = match(head, "\") let buf = strpart(head, 0, idx) let head = strpart(head, idx+1) let idx = match(buf, ': ') let file = strpart(buf, 0, idx) let title = strpart(buf, idx+2) let title = substitute(title, '^'.g:orememo_title, '', '') if title == '' continue endif let b:orememofile{i} = file let s:orememoline{b:orememofile{i}} = title let i = i + 1 endwhile return i endfun "" 行読み込み、解析 -------------------------------------------------- function! s:OreMemoParseLine() let line = getline('.') if exists('g:orememo_wwwprg') && line =~ '[hf]ttp[s:]./' let url = substitute(line, '.*\([hf]ttp[s:].[a-zA-Z0-9-_.!%~*/?:@&=+$,#;]\+\).*', '\1', '') let cmd = substitute(g:orememo_wwwprg, '%URL%', url, 'g') let cmd = escape(cmd, '%#') exe '!'.cmd else exe "normal! \" endif endfun "" 共通コマンドセット ------------------------------------------------ function! s:SetOreMemoCommand() command! -buffer -nargs=1 OMemoHelp call s:OreMemoHelp() command! -buffer -nargs=1 OMemoOpen call s:OreMemoOpen() command! -buffer -nargs=1 OMemoQuit call s:OreMemoQuit() command! -buffer -nargs=1 OMemoRemove call s:OreMemoRemove() nnoremap D :OMemoRemove() nnoremap ? :OMemoHelp() nnoremap :OMemoOpen(0) nnoremap O :OMemoOpen(3) nnoremap o :OMemoOpen(-1) nnoremap p :OMemoOpen(2) nnoremap q :OMemoQuit() endfun "" 共通コマンドセット ------------------------------------------------ function! s:SetOreMemoViewCommand() command! -buffer -nargs=1 OMemoParseLine call s:OreMemoParseLine() nnoremap :OMemoParseLine() endfun "" OreMemoList のウィンドウを選択 ------------------------------------ function! s:OreMemoSetWin() let winno = bufwinnr("OreMemoList.orememo") if winno != -1 exe winno.'wincmd w' endif silent! exe 'wincmd w' let winno2 = winnr() if winno == winno2 if s:orememosplitmode != '' exe g:orememo_splitsize.s:orememosplitmode.'split' endif silent! exe 'wincmd w' endif endfun " -------------------------------------------------------------------- " GPG 関連の処理 " -------------------------------------------------------------------- "" GPG ファイルのリスト ---------------------------------------------- function! s:OreMemoGpgList(i) let f = 0 while exists('g:orememo_gpglist'.f) call append('$', (a:i + f) . ": " . g:orememo_gpglist{f}) let b:orememosec{(a:i+f)} = f.'.oregpg' let f = f + 1 endwhile endfun "" GPG 複合化 -------------------------------------------------------- function! s:OreMemoGpgDecrypt() let b:orememogpgopen = 0 echo '' silent! setlocal bin if getfsize(expand('%:p')) >= 0 if g:orememo_gpgpassphrase == 1 if has('perl') call s:OreMemoPerlGpgDecrypt() else if !exists('g:orememopassphrase') let g:orememopassphrase = inputsecret('Enter passphrase: ') endif exe "%!echo ".g:orememopassphrase." | gpg --batch --passphrase-fd 0 --quiet --decrypt ".expand('%:p')." 2>/dev/null" endif else exe "%!gpg --quiet --decrypt 2>/dev/null" endif endif silent! setlocal updatetime=9999999 nobuflisted bufhidden=delete silent! setlocal nobin if v:shell_error == 2 || b:orememogpgopen == 1 let result = confirm('Invalid passphrase') if !exists('g:orememopassphrase') let g:orememopassphrase = '' endif let b:orememogpgopen = 1 call s:OreMemoEditFile('OreMemoGpgTmp.orememo', 0, 0) setlocal nomodifiable endif redraw! endfun "" GPG 暗号化&保存 --------------------------------------------------- function! s:OreMemoGpgEncrypt() if b:orememogpgopen == 0 let line = line('.') let col = col('.') silent! set buftype= silent! set bin silent! exe '%!gpg --armor --encrypt --recipient '.g:orememo_gpgrecipient silent! update if g:orememo_gpgpassphrase == 1 call s:OreMemoGpgDecrypt() call cursor(line, col) redraw! else call s:OreMemoEditFile('OreMemoGpgTmp.orememo', 0, 0) endif endif endfun " -------------------------------------------------------------------- " Perl 関連の処理 " -------------------------------------------------------------------- "" 検索解析処理 Perl 版 ---------------------------------------------- function! s:OreMemoPerlParseSearch(grep) let grep = g:orememo_grepprg . ' -n ' . a:grep perl <<_PERL_ { my (@lines, %HASH); my $grep = VIM::Eval('grep'); my $mtitle = VIM::Eval('g:orememo_title'); my @result = `$grep`; my $count = 1; foreach (@result) { chomp(); /([^:]*\/([^\/^:]+).orememo):(\d+):(.*)/; my ($full, $file, $num, $line) = ($1, $2, $3, $4); next if($file eq ''); $file = $1.'/'.$file if($full =~ /\/([^\/]+\.orememo)\//); unless($HASH{$file}) { open(IN, $full); my $title = ; close(IN); chomp($title); $title =~ s/^$mtitle//; $HASH{$file} = $title; } VIM::DoCommand("let b:orememofile{$count} = '$file'"); VIM::DoCommand("let b:orememonum{$count} = '$num'"); push(@lines, "$count: $HASH{$file} : $line"); $count++; } $curbuf->Append(2, @lines) if(@lines); } _PERL_ endfun "" タイトルリスト読み込み Perl 版 ------------------------------------ function! s:OreMemoPerlReadHead() perl <<_PERL_ { my @HASH; my $count = 0; my $dir = VIM::Eval('s:orememodir'); my $sort = VIM::Eval('g:orememo_sort'); my $mtitle = VIM::Eval('g:orememo_title'); opendir(DIR, $dir); while (my $file = readdir(DIR)) { next if($file !~ /\.orememo$/ or -d "$dir/$file"); open(IN, $dir.$file); my $title = ; close(IN); chomp($title); $title =~ s/^$mtitle//; $HASH[$count]->{'sort'} = (stat($dir.$file))[9]; $file =~ s/\.orememo$//; $HASH[$count]->{'title'} = $title; $HASH[$count]->{'file'} = $file; $count++; } close(DIR); if($sort =~ /t/) { my @idx = (0..$#HASH); @idx = sort { $HASH[$b]->{'sort'} <=> $HASH[$a]->{'sort'} || $a <=> $b } @idx; @HASH = @HASH[@idx]; } @HASH = reverse(@HASH) if($sort =~ /r/); $count = 0; my @lines; foreach (@HASH) { $count++; VIM::DoCommand("let b:orememofile{$count} = '$_->{'file'}'"); push(@lines, "${count}: $_->{'title'}"); } $curbuf->Append('3', @lines); VIM::DoCommand("let i = $count + 1"); } _PERL_ return i endfun "" GPG 複合化 Perl版 ------------------------------------------------- function! s:OreMemoPerlGpgDecrypt() let b:orememogpgopen = 1 perl <<_PERL_ { use GnuPG::Tie::Decrypt; my $num = $curbuf->Count(); my @lines = $curbuf->Get(1 .. $num); my $passphrase = $pass; $passphrase = VIM::Eval('inputsecret("Enter passphrase: ")') if($pass eq ''); tie *DecText, 'GnuPG::Tie::Decrypt', passphrase => $passphrase; print DecText join("\n", @lines); my @text = ; close DecText; untie *DecText; map { chomp; } @text; $pass = $passphrase; VIM::DoCommand('let b:orememogpgopen = 0'); $curbuf->Delete(1, $num); $curbuf->Append(0, @text); $curbuf->Delete($curbuf->Count()); } _PERL_ endfun " -------------------------------------------------------------------- " 最初の読み込み " -------------------------------------------------------------------- "" 初期化処理 -------------------------------------------------------- function! s:OreMemoInit() " data directory if !exists('g:orememo_dir') let g:orememo_dir = '~/.orememo/' endif " title if !exists('g:orememo_title') let g:orememo_title = '= ' endif " auto preview if !exists('g:orememo_autopreview') let g:orememo_autopreview = 0 endif " split mode if !exists('g:orememo_splitmode') let g:orememo_splitmode = 0 endif " split size if !exists('g:orememo_splitsize') let g:orememo_splitsize = 20 endif " default sort if !exists('g:orememo_sort') let g:orememo_sort = 't' endif " buffer if !exists('g:orememo_buffer') let g:orememo_buffer = 0 endif " updatetime if !exists('g:orememo_updatetime') let g:orememo_updatetime = 200 endif " backup if !exists('g:orememo_backup') let g:orememo_backup = 0 endif " grep if !exists('g:orememo_grepprg') let g:orememo_grepprg = 'grep' endif " grep option if !exists('g:orememo_grepopt') let g:orememo_grepopt = 'rE' endif " clgrep if !exists('g:orememo_clgrepprg') let g:orememo_clgrepprg = '' endif " head option if !exists('g:orememo_headopt') let g:orememo_headopt = 'v' endif " use gpg if !exists('g:orememo_gpg') || !exists('g:orememo_gpgrecipient') let g:orememo_gpg = 0 endif " gpg passphrase if !exists('g:orememo_gpgpassphrase') let g:orememo_gpgpassphrase = 0 endif let s:orememodir = expand(g:orememo_dir) if s:orememodir != '' && s:orememodir !~ "/$" let s:orememodir = s:orememodir . '/' endif if g:orememo_splitmode == 0 let s:orememosplitmode = 'v' elseif g:orememo_splitmode == 1 let s:orememosplitmode = ' ' else let s:orememosplitmode = '' endif " message catalogue if v:lang == 'ja_JP.eucJP' let s:msg_list_help = 'ヘルプ' let s:msg_list_ret = 'メモを開く' let s:msg_list_open = '(Diary|clmemo|orememo)モードでも、日付を挿入しないでメモを開く' let s:msg_list_open2 = '一つのウィンドウでメモを開く' let s:msg_list_preview = 'メモをプレビュー' let s:msg_list_reload = '再読み込み' let s:msg_list_delete = 'メモを削除' let s:msg_list_toggle = '並び替え' let s:msg_list_quit = '終了' let s:msg_list_sort = '現在の並び順' let s:msg_search_input = '検索文字列 : ' let s:msg_search_result= '検索文字列' let s:msg_conf_delete = '本当に削除しますか?' let s:msg_error_nodir = 'OreMemo エラー: データディレクトリ'.g:orememo_dir.'が見付かりません。' else let s:msg_list_help = 'help' let s:msg_list_ret = 'open memo' let s:msg_list_open = '*open memo' let s:msg_list_open2 = 'open memo in one window' let s:msg_list_preview = 'preview memo' let s:msg_list_reload = 'reload list' let s:msg_list_delete = 'delete entry' let s:msg_list_toggle = 'toggle sort' let s:msg_list_quit = 'quit the OreMemo' let s:msg_list_sort = 'now sorted by' let s:msg_search_input = 'Input Word : ' let s:msg_search_result= 'Search Word' let s:msg_conf_delete = 'Delete?' let s:msg_error_nodir = "OreMemo error: Can't find data dir '".g:orememo_dir."'" endif if !isdirectory(s:orememodir) echo s:msg_error_nodir return 0 endif command! OreMemo call s:OreMemoMain() command! OreMemoNew call s:OreMemoOpen(1) command! OreMemoSearch call s:OreMemoSearch() command! -nargs=? OreMemoClGrep call s:OreMemoClGrep() augroup orememo if g:orememo_autopreview == 1 autocmd CursorHold OreMemoList.orememo call s:OreMemoOpen(2) autocmd CursorHold OreMemoSearch.orememo call s:OreMemoOpen(2) endif autocmd CursorHold *.orememo update! autocmd BufLeave *.orememo update! autocmd BufRead,BufNewFile *.orememo set filetype=OreMemo if g:orememo_gpg == 1 autocmd! FileWritePost,BufWritePost *.oregpg call s:OreMemoGpgEncrypt() autocmd! BufNewFile,BufReadPost,FileReadPost *.oregpg call s:OreMemoGpgDecrypt() endif augroup END endfun call s:OreMemoInit()