自己写了个,用sqlite来保存数据.
将下面代码存为 SzTodo.vim,放到plugin目录里.
用 :SzTodo 启动.
let g:sztodo_db_path="/root/.vim/todo" let s:list_type="unfinished" let s:cur_buf = 0 function! MakeTemplate() python << EOF import vim vim.command("call SwitchToDetailView()") vim.command("call SetSyntax()") template = "=" * 50 + "\n" \ + "tag:" +"\n" \ + "title:" + "\n" \ + "=" * 50 + "\n" for index,line in enumerate(template.split("\n")): if index ==0 : vim.current.buffer[0]=line else : vim.current.buffer.append(line) EOF endfunction function! SaveTodoItem() python << EOF import vim def loadData(lines): item=ToDoItem() content="" seperates=0 for line in lines: if line.startswith("====="): seperates=seperates+1 if line.startswith("id:"): item.id=line[3:].strip() if line.startswith("tag:"): item.tag=line[4:].strip() if line.startswith("title:"): item.title=line[6:].strip() if line.startswith("status:"): item.status=line[7:].strip() if seperates==2 and not line.startswith("===="): content=content+line+"\n" item.content=content[:-1] return item def addItem(item): insertSql="insert into SzTodo(tag,title,create_date,status,content) values (?,?,?,?,?)" con=sqlite.connect(getDbFileName()) cur=con.cursor() values=(item.tag,item.title,item.create_date,item.status,item.content) cur.execute(insertSql,values) con.commit() con.close() def updateItem(item): updateSql="update SzTodo set tag=?,title=?,create_date=?,status=?,content=? where id=?" con=sqlite.connect(getDbFileName()) cur=con.cursor() values=(item.tag,item.title,item.create_date,item.status,item.content,item.id) cur.execute(updateSql,values) con.commit() con.close() data=vim.current.buffer[:] todoItem=loadData(data) if not todoItem.title: print "title can't be empty" else: if todoItem.id.strip() == "" : todoItem.create_date=getCurrentDate() todoItem.status="unstarted" addItem(todoItem) else : updateItem(todoItem) print "todo has been saved" EOF exec bufwinnr(s:cur_buf) . "wincmd w" call ListItems() endfunction function! ListItems() python << EOF import vim listFinished=vim.eval("s:list_type") vim.current.buffer[:]=None vim.command("set nonumber") if listFinished=="finished": selectSql="select id,tag,title,create_date,content from SzTodo where status == 'done' " else: selectSql="select id,tag,title,create_date,content from SzTodo where status != 'done' " con=sqlite.connect(getDbFileName()) cur=con.cursor() items=[] cur.execute(selectSql) for index,row in enumerate(cur): formatedItem=str(row[0])+". "+str(unicode(row[2]).encode("utf-8")) if index==0: vim.current.buffer[0]=formatedItem else : vim.current.buffer.append(formatedItem) con.commit() con.close() EOF endfunction function! SwitchToDetailView() let s:cur_buf = bufnr("%") let s:szdb_result_buf=bufnr("SztodoDetail") if bufwinnr(s:szdb_result_buf) > 0 exec bufwinnr(s:szdb_result_buf) . "wincmd w" %d else exec 'silent! botright split SztodoDetail' exec "e SztodoDetail" exec "set nowrap" maps :call SaveTodoItem() endif endfunction function! ShowItemDetail(preview) python << EOF import vim (row, col) = vim.current.window.cursor line = vim.current.buffer[row-1] id=line[0:line.find(".")] selectSql="select id,tag,title,create_date,content,status from SzTodo where id=?" con=sqlite.connect(getDbFileName()) cur=con.cursor() cur.execute(selectSql,(id,)) todoItem=ToDoItem() for row in cur: todoItem.id=row[0] todoItem.tag=unicode(row[1]).encode("utf-8") todoItem.title=unicode(row[2]).encode("utf-8") todoItem.create_date=unicode(row[3]).encode("utf-8") todoItem.content=unicode(row[4]).encode("utf-8") todoItem.status=unicode(row[5]).encode("utf-8") vim.command("call SwitchToDetailView()") vim.command("call SetSyntax()") for index,line in enumerate(str(todoItem).split("\n")): if index==0: vim.current.buffer[0]=line else: vim.current.buffer.append(line) EOF if a:preview=="true" exec bufwinnr(s:cur_buf) . "wincmd w" endif endfunction function! UpdateItemStatus(status) let choice=input('you really want to update the todo item status to '.a:status."?[y/n]") if choice=="n" return endif python << EOF import vim (row, col) = vim.current.window.cursor line = vim.current.buffer[row-1] id=line[0:line.find(".")] updateSql="update SzTodo set status = ? where id=?" status=vim.eval("a:status") con=sqlite.connect(getDbFileName()) cur=con.cursor() cur.execute(updateSql,(status,id)) con.commit() con.close() EOF endfunction function! InitDb() python << EOF import vim import os createSql="create table SzTodo (id integer primary key , tag char(20), title varchar(200), \ create_date varchar(10),status char(1),content varchar(5000))" path=os.path.dirname(getDbFileName()) if not os.path.exists(path): os.makedirs(path) con=sqlite.connect(getDbFileName()) cur=con.cursor() cur.execute(createSql) con.commit() con.close() print "db has been created" EOF endfunction function! s:DefSzTodoGlobal() python << EOF import vim from pysqlite2 import dbapi2 as sqlite statusDict=dict(done="done",postpone="postpone",doing="doing",unstarted="unstarted") class ToDoItem(object): def __init__(self,id="",tag="",title="",content="",create_date="",status=""): self.id=id self.tag=tag self.title=title self.create_date=create_date self.status=status self.content=content def __str__(self): return "=" * 50 + "\n" \ + "id:" + str(self.id) +"\n" \ + "tag:" + self.tag +"\n" \ + "title:" + self.title + "\n" \ + "status:" + self.status + "\n" \ + "=" * 50 + "\n" \ + self.content def getCurrentDate(): from datetime import datetime t=datetime.now() return t.strftime("%Y-%m-%d %H:%M") def getDbFileName(): dbpath=vim.eval("g:sztodo_db_path") path=os.path.join(dbpath,"todo.dat") return path EOF endfunction function! StartApp() python << EOF import vim import os if not os.path.exists(getDbFileName()): vim.command("call InitDb()") vim.command("call ListItems()") vim.command("call SetMapping()") EOF endfunction function! SetMapping() map o :call ShowItemDetail("false") map s :call ShowItemDetail("true") map i :call MakeTemplate() map r :call ListItems() map p :call UpdateItemStatus("postpone") map d :call UpdateItemStatus("done") command! -nargs=0 FinishedItem :call FinishedItem() command! -nargs=0 UnfinishedItem :call UnfinishedItem() endfunction function! FinishedItem() let s:list_type="finished" call ListItems() endfunction function! UnfinishedItem() let s:list_type="unfinished" call ListItems() endfunction function! SetSyntax() syn keyword sztodoKeyword tag title id status syn keyword sztodoStatus unstarted done doing postpone syn match tag "^tag:.*" syn match title "^title:.*" syn match id "^id:.*" syn match status "^status:.*" hi def link sztodoKeyword Keyword hi def link sztodoStatus Identifier hi def link tag String hi def link id String hi def link title String hi def link status String endfunction call s:DefSzTodoGlobal() command! -nargs=0 SzTodo :call StartApp()