python写vim script 之 山寨版 GTD

阅读更多
一直想找个用vim来管理todo列表的script, 没发现特别好用的,
自己写了个,用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"  
    map s :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()




你可能感兴趣的:(vim,Python,SQLite,OS)