zim-wiki team mailing list archive
-
zim-wiki team
-
Mailing list archive
-
Message #02013
Re: CLI?
Hi,
I've been tuning and tweaking a bit to get things to sort of work.
I already had a working installation of DokuVimKi vim plugin on my
computer and decided to just copy those files to something I called
zimvimki.vim locally. Everything "doku" became "zim" both in lower and
upper case, and anything "DW" became "ZW" to distinguish zim from
dokuwiki.
Now I can open a zim notebook in ZimVimKi and edit files and pages not
containing whitespaces. I still have the old page naming rule from
dokuwiki in my plugin and need to root this out, and I can still not
save any changes I make to the pages I am able to edit.
>From my work, I see that the zimwikiclient needs to be put in the
general python path so that it is reachable by vim. That means it should
have a home in the general zim python install. Alternative is to extend
the sys.path
I've done things easy for myself, and have that in mind when trying out
what I have done.
Put zimvimki.vim and my modified zimwikiclient.py in .vim/plugin and
zimvimki.txt in .vim/doc and give it a try. Edit .vimrc and add
let g:ZimVimKi_URL = '/home/user/path/to/zim/Notes/'
Fire up vim, no errors should happen, and run :ZimVimKi
Remember that many features available in DokuVimKi is not yet available
or working as expected.
--
Svenn
"-----------------------------------------------------------------------------
" Copyright (C) 2010 Michael Klier <chi@xxxxxxxxxxx>
"
" This program is free software; you can redistribute it and/or modify
" it under the terms of the GNU General Public License as published by
" the Free Software Foundation; either version 2, or (at your option)
" any later version.
"
" This program is distributed in the hope that it will be useful,
" but WITHOUT ANY WARRANTY; without even the implied warranty of
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
" GNU General Public License for more details.
"
" You should have received a copy of the GNU General Public License
" along with this program; if not, write to the Free Software Foundation,
" Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
"
" Maintainer: Michael Klier <chi@xxxxxxxxxxx>
" URL: http://www.chimeric.de/projects/zimuwiki/zimvimki
"-----------------------------------------------------------------------------
if has('python') && version > 700
command! -nargs=0 ZimVimKi exec('py zimvimki()')
if !exists('g:ZimVimKi_INDEX_WINWIDTH')
let g:ZimVimKi_INDEX_WINWIDTH=30
endif
if !exists('g:ZimVimKi_DEFAULT_SUM')
let g:ZimVimKi_DEFAULT_SUM = '[xmlrpc zimvimki edit]'
endif
" Custom autocompletion function for wiki pages and media files
" the global g:pages g:media variables are set/refreshed
" when the index is loaded
fun! InsertModeComplete(findstart, base)
if a:findstart
" locate the start of the page/media link
let line = getline('.')
let start = col('.') - 1
while start > 0 && line[start - 1] !~ '\([\|{\)'
let start -= 1
endwhile
if line[start - 1] =~ "["
let g:comp = "pages"
elseif line[start - 1] =~ "{"
let g:comp = "media"
endif
return start
else
" find matching pages/media
let res = []
if g:comp =~ "pages"
for m in split(g:pages)
if m =~ '^' . a:base
call add(res, m)
endif
endfor
elseif g:comp =~ "media"
for m in split(g:media)
if m =~ '^' . a:base
call add(res, m)
endif
endfor
endif
return res
endif
endfun
" Custom autocompletion function for namespaces and pages in
" normal mode. Used with ZWedit
fun! CmdModeComplete(ArgLead, CmdLine, CursorPos)
let res = []
for m in split(g:pages)
if m =~ '^' . a:ArgLead
call add(res, m)
endif
endfor
return res
endfun
" Inserts a headline
let g:headlines = ["====== ======", "===== =====", "==== ====", "=== ===", "== =="]
fun! Headline()
return g:headlines[g:lvl]
endfun
" Sets indentation/headline level
let g:lvl = 0
fun! SetLvl(lvl)
let nlvl = g:lvl + a:lvl
if nlvl >= 1 && nlvl <= 4
let g:lvl = nlvl
endif
return ''
endfun
python <<EOF
# -*- coding: utf-8 -*-
__version__ = '2010-07-01';
__author__ = 'Michael Klier <chi@xxxxxxxxxxx>'
import sys
import os
import re
import vim
import time
sys.path.append('/home/svenn/.vim/plugin')
try:
import zimwikiclient
has_zimwikiclient = True
except ImportError:
print >>sys.stderr, 'ZimVimKi Error: The zimwikiclient python module is missing!'
print os.getcwd()
has_zimwikiclient = False
class ZimVimKi:
"""
Provides all necessary functionality to interface between the ZimWiki
XMLRPC API and vim.
"""
def __init__(self):
"""
Instantiates special buffers, setup the xmlrpc connection and loads the
page index and displays the recent changes of the last 7 days.
"""
if sys.version_info < (2,4):
print >>sys.stderr, "ZimVimKi requires at least python Version 2.4 or greater!"
return
if not has_zimwikiclient:
print >>sys.stderr, "zimwikiclient python module missing!"
return
if self.xmlrpc_init():
vim.command("command! -complete=customlist,CmdModeComplete -nargs=1 ZWedit exec('py zimvimki.edit(<f-args>)')")
vim.command("command! -complete=customlist,CmdModeComplete -nargs=* ZWcd exec('py zimvimki.cd(<f-args>)')")
vim.command("command! -nargs=? ZWsave exec('py zimvimki.save(<f-args>)')")
vim.command("command! -nargs=? ZWsearch exec('py zimvimki.search(\"page\", <f-args>)')")
vim.command("command! -nargs=? ZWmediasearch exec('py zimvimki.search(\"media\", <f-args>)')")
vim.command("command! -complete=customlist,CmdModeComplete -nargs=* ZWrevisions exec('py zimvimki.revisions(<f-args>)')")
vim.command("command! -complete=customlist,CmdModeComplete -nargs=? ZWbacklinks exec('py zimvimki.backlinks(<f-args>)')")
vim.command("command! -nargs=? ZWchanges exec('py zimvimki.changes(<f-args>)')")
vim.command("command! -nargs=0 -bang ZWclose exec('py zimvimki.close(\"<bang>\")')")
vim.command("command! -nargs=0 ZWdiffclose exec('py zimvimki.diff_close()')")
vim.command("command! -complete=file -bang -nargs=1 ZWupload exec('py zimvimki.upload(<f-args>,\"<bang>\")')")
vim.command("command! -nargs=0 ZWhelp exec('py zimvimki.help()')")
vim.command("command! -nargs=0 -bang ZWquit exec('py zimvimki.quit(\"<bang>\")')")
self.buffers = {}
self.buffers['search'] = Buffer('search', 'nofile')
self.buffers['backlinks'] = Buffer('backlinks', 'nofile')
self.buffers['revisions'] = Buffer('revisions', 'nofile')
self.buffers['changes'] = Buffer('changes', 'nofile')
self.buffers['index'] = Buffer('index', 'nofile')
self.buffers['media'] = Buffer('media', 'nofile')
self.buffers['help'] = Buffer('help', 'nofile')
self.needs_refresh = False
self.diffmode = False
self.cur_ns = ''
self.pages = []
self.default_sum = vim.eval('g:ZimVimKi_DEFAULT_SUM')
self.index_winwith = vim.eval('g:ZimVimKi_INDEX_WINWIDTH')
self.index(self.cur_ns, True)
vim.command('set laststatus=2')
vim.command('silent! ' + self.index_winwith + 'vsplit')
self.help()
vim.command("command! -nargs=0 ZimVimKi echo 'ZimVimKi is already running!'")
def xmlrpc_init(self):
"""
Establishes the xmlrpc connection to the remote wiki.
"""
try:
self.dw_user = vim.eval('g:ZimVimKi_USER')
self.dw_pass = vim.eval('g:ZimVimKi_PASS')
self.dw_url = vim.eval('g:ZimVimKi_URL')
except vim.error, err:
print >>sys.stderr, "Something went wrong during initialization. Please check your configuration settings."
return False
try:
#self.xmlrpc = zimwikiclient.ZimWikiClient(self.dw_url, self.dw_user, self.dw_pass)
self.xmlrpc = zimwikiclient.ZimWikiClient(self.dw_url)
print >>sys.stdout, 'Connection to ' + vim.eval('g:ZimVimKi_URL') + ' established!'
return True
except vim.error, err:
print >>sys.stderr, err
return False
def edit(self, wp, rev=''):
"""
Opens a given wiki page, or a given revision of a wiki page for
editing or switches to the correct buffer if the is open already.
"""
wp = wp.strip()
if wp.find(' ') != -1:
print >>sys.stderr, "Pagenames cannot contain whitespace. Please use valid pagenames only!\nSee http://zimuwiki.org/pagename"
return
if self.diffmode:
self.diff_close()
self.focus(2)
if wp.find(':') == -1:
wp = self.cur_ns + wp
if not self.buffers.has_key(wp):
perm = int(self.xmlrpc.acl_check(wp))
if perm >= 1:
try:
if rev:
text = self.xmlrpc.page(wp, int(rev))
else:
text = self.xmlrpc.page(wp)
except zimwikiclient.ZimWikiXMLRPCError, err:
print >>sys.stdout, err
if text:
if perm == 1:
print >>sys.stderr, "You don't have permission to edit %s. Opening readonly!" % wp
self.buffers[wp] = Buffer(wp, 'nowrite', True)
lines = text.split("\n")
self.buffers[wp].buf[:] = map(lambda x: x.encode('utf-8'), lines)
vim.command('setlocal nomodifiable')
vim.command('setlocal readonly')
if perm >= 2:
if not self.lock(wp):
return
print >>sys.stdout, "Opening %s for editing ..." % wp
self.buffers[wp] = Buffer(wp, 'acwrite', True)
lines = text.split("\n")
self.buffers[wp].page[:] = map(lambda x: x.encode('utf-8'), lines)
self.buffers[wp].buf[:] = self.buffers[wp].page
vim.command('set nomodified')
vim.command('autocmd! BufWriteCmd <buffer> py zimvimki.save()')
vim.command('autocmd! FileWriteCmd <buffer> py zimvimki.save()')
vim.command('autocmd! FileAppendCmd <buffer> py zimvimki.save()')
if not text and perm >= 4:
print >>sys.stdout, "Creating new page: %s" % wp
self.buffers[wp] = Buffer(wp, 'acwrite', True)
self.needs_refresh = True
vim.command('set nomodified')
vim.command('autocmd! BufWriteCmd <buffer> py zimvimki.save()')
vim.command('autocmd! FileWriteCmd <buffer> py zimvimki.save()')
vim.command('autocmd! FileAppendCmd <buffer> py zimvimki.save()')
self.buffer_setup()
else:
print >>sys.stderr, "You don't have permissions to read/edit/create %s" % wp
return
else:
self.needs_refresh = False
vim.command('silent! buffer! ' + self.buffers[wp].num)
def diff(self, revline):
"""
Opens a page and a given revision in diff mode.
"""
data = revline.split()
wp = data[0]
rev = data[2]
date = time.strftime('%Y-%m-%d@%Hh%mm%Ss', time.localtime(float(rev)))
if not self.buffers.has_key(wp):
self.edit(wp)
if not self.buffers[wp].diff.has_key(rev):
text = self.xmlrpc.page(wp, int(rev))
if text:
self.buffers[wp].diff[rev] = Buffer(wp + '_' + date, 'nofile')
lines = text.split("\n")
self.buffers[wp].diff[rev].page[:] = map(lambda x: x.encode('utf-8'), lines)
else:
print >>sys.stdout, "Error, couldn't load revision for diffing."
return
self.focus(2)
vim.command('silent! buffer! ' + self.buffers[wp].num)
vim.command('vertical diffsplit')
self.focus(3)
vim.command('silent! buffer! ' + self.buffers[wp].diff[rev].num)
vim.command('setlocal modifiable')
vim.command('abbr <buffer> close ZWdiffclose')
vim.command('abbr <buffer> ZWclose ZWdiffclose')
self.buffers[wp].diff[rev].buf[:] = self.buffers[wp].diff[rev].page
vim.command('setlocal nomodifiable')
self.buffer_setup()
vim.command('diffthis')
self.focus(2)
self.diffmode = True
def diff_close(self):
"""
Closes the diff window.
"""
self.focus(3)
vim.command('diffoff')
vim.command('close')
self.diffmode = False
self.focus(2)
vim.command('vertical resize')
def save(self, sum='', minor=0):
"""
Saves the current buffer. Works only if the buffer is a wiki page.
Deleting wiki pages works like using the web interface, just delete all
text and save.
"""
wp = vim.current.buffer.name.rsplit('/', 1)[1]
try:
if not self.buffers[wp].iswp:
print >>sys.stderr, "Error: Current buffer %s is not a wiki page or not writeable!" % wp
elif self.buffers[wp].type == 'nowrite':
print >>sys.stderr, "Error: Current buffer %s is readonly!" % wp
else:
text = "\n".join(self.buffers[wp].buf)
if text and not self.ismodified(wp):
print >>sys.stdout, "No unsaved changes in current buffer."
elif not text and not wp in self.pages:
print >>sys.stdout, "Can't save new empty page %s." % wp
else:
if not sum and text:
sum = self.default_sum
minor = 1
try:
self.xmlrpc.put_page(wp, text, sum, minor)
self.buffers[wp].page[:] = self.buffers[wp].buf
self.buffers[wp].need_save = False
if text:
vim.command('silent! buffer! ' + self.buffers[wp].num)
vim.command('set nomodified')
print >>sys.stdout, 'Page %s written!' % wp
if self.needs_refresh:
self.index(self.cur_ns, True)
self.needs_refresh = False
self.focus(2)
else:
print >>sys.stdout, 'Page %s removed!' % wp
self.close(False)
self.index(self.cur_ns, True)
self.focus(2)
except zimwikiclient.ZimWikiXMLRPCError, err:
print >>sys.stderr, 'ZimVimKi Error: %s' % err
except KeyError, err:
print >>sys.stderr, "Error: Current buffer %s is not handled by ZWsave!" % wp
def upload(self, file, overwrite=False):
"""
Uploads a file to the remote wiki.
"""
path = os.path.realpath(file)
fname = os.path.basename(path)
if os.path.isfile(path):
try:
fh = open(path, 'r')
data = fh.read()
file_id = self.cur_ns + fname
try:
self.xmlrpc.put_file(file_id, data, overwrite)
print >>sys.stdout, "Uploaded %s successfully." % fname
self.refresh()
except zimwikiclient.ZimWikiXMLRPCError, err:
print >>sys.stderr, err
except IOError, err:
print >>sys.stderr, err
else:
print >>sys.stderr, '%s is not a file' % path
def cd(self, query=''):
"""
Changes into the given namespace.
"""
if query and query[-1] != ':':
query += ':'
self.index(query)
def index(self, query='', refresh=False):
"""
Build the index used to navigate the remote wiki.
"""
index = []
pages = []
dirs = []
self.focus(1)
vim.command('set winwidth=' + self.index_winwith)
vim.command('set winminwidth=' + self.index_winwith)
vim.command('silent! buffer! ' + self.buffers['index'].num)
vim.command('setlocal modifiable')
vim.command('setlocal nonumber')
vim.command('syn match ZimVimKi_NS /^.*\//')
vim.command('syn match ZimVimKi_CURNS /^ns:/')
vim.command('hi ZimVimKi_NS term=bold cterm=bold ctermfg=LightBlue gui=bold guifg=LightBlue')
vim.command('hi ZimVimKi_CURNS term=bold cterm=bold ctermfg=Yellow gui=bold guifg=Yellow')
if refresh:
self.refresh()
if query and query[-1] != ':':
self.edit(query)
return
else:
self.cur_ns = query
if self.pages:
for page in self.pages:
if not query:
if page.find(':', 0) == -1:
pages.append(page)
else:
ns = page.split(':', 1)[0] + '/'
if ns not in dirs:
dirs.append(ns)
else:
if re.search('^' + query, page):
page = page.replace(query, '')
if page.find(':') == -1:
if page not in index:
pages.append(page)
else:
ns = page.split(':', 1)[0] + '/'
if ns not in dirs:
dirs.append(ns)
index.append('ns: ' + self.cur_ns)
if query:
index.append('.. (up a namespace)')
index.append('')
pages.sort()
dirs.sort()
index = index + dirs + pages
self.buffers['index'].buf[:] = index
vim.command('map <silent> <buffer> <enter> :py zimvimki.cmd("index")<CR>')
vim.command('map <silent> <buffer> r :py zimvimki.cmd("revisions")<CR>')
vim.command('map <silent> <buffer> b :py zimvimki.cmd("backlinks")<CR>')
vim.command('setlocal nomodifiable')
vim.command('2')
def changes(self, timeframe=False):
"""
Shows the last changes on the remote wiki.
"""
if self.diffmode:
self.diff_close()
self.focus(2)
vim.command('silent! buffer! ' + self.buffers['changes'].num)
vim.command('setlocal modifiable')
if not timeframe:
timestamp = int(time.time()) - (60*60*24*7)
else:
m = re.match(r'(?P<num>\d+)(?P<type>[dw]{1})', timeframe)
if m:
argv = m.groupdict()
if argv['type'] == 'd':
timestamp = int(time.time()) - (60*60*24*int(argv['num']))
elif argv['type'] == 'w':
timestamp = int(time.time()) - (60*60*24*(int(argv['num'])*7))
else:
print >>sys.stderr, "Wrong timeframe format %s." % timeframe
return
else:
print >>sys.stderr, "Wrong timeframe format %s." % timeframe
return
try:
changes = self.xmlrpc.recent_changes(timestamp)
lines = []
if len(changes) > 0:
maxlen = 0;
for change in changes:
changelen = len(change['name'])
if changelen > maxlen:
maxlen = changelen
for change in changes:
change['name'] = change['name'] + ' ' * (maxlen - len(change['name']))
line = "\t".join(map(lambda x: str(change[x]), ['name', 'lastModified', 'version', 'author']))
lines.append(line)
lines.reverse()
self.buffers['changes'].buf[:] = lines
vim.command('syn match ZimVimKi_REV_PAGE /^\(\w\|:\)*/')
vim.command('syn match ZimVimKi_REV_TS /\s\d*\s/')
vim.command('hi ZimVimKi_REV_PAGE cterm=bold ctermfg=Yellow gui=bold guifg=Yellow')
vim.command('hi ZimVimKi_REV_TS cterm=bold ctermfg=Yellow gui=bold guifg=Yellow')
vim.command('setlocal nomodifiable')
vim.command('map <silent> <buffer> <enter> :py zimvimki.rev_edit()<CR>')
else:
print >>sys.stderr, 'ZimVimKi Error: No changes'
except zimwikiclient.ZimWikiXMLRPCError, err:
print >>sys.stderr, err
def revisions(self, wp='', first=0):
"""
Display revisions for a certain page if any.
"""
if self.diffmode:
self.diff_close()
if not wp or wp[-1] == ':':
return
try:
self.focus(2)
vim.command('silent! buffer! ' + self.buffers['revisions'].num)
vim.command('setlocal modifiable')
revs = self.xmlrpc.page_versions(wp, int(first))
lines = []
if len(revs) > 0:
for rev in revs:
line = wp + "\t" + "\t".join(map(lambda x: str(rev[x]), ['modified', 'version', 'ip', 'type', 'user', 'sum']))
lines.append(line)
self.buffers['revisions'].buf[:] = lines
print >>sys.stdout, "loaded revisions for :%s" % wp
vim.command('map <silent> <buffer> <enter> :py zimvimki.rev_edit()<CR>')
vim.command('syn match ZimVimKi_REV_PAGE /^\(\w\|:\)*/')
vim.command('syn match ZimVimKi_REV_TS /\s\d*\s/')
vim.command('syn match ZimVimKi_REV_CHANGE /\s\w\{1}\s/')
vim.command('hi ZimVimKi_REV_PAGE term=bold cterm=bold ctermfg=Yellow gui=bold guifg=Yellow')
vim.command('hi ZimVimKi_REV_TS term=bold cterm=bold ctermfg=Yellow gui=bold guifg=Yellow')
vim.command('hi ZimVimKi_REV_CHANGE term=bold cterm=bold ctermfg=Yellow gui=bold guifg=Yellow')
vim.command('setlocal nomodifiable')
vim.command('map <silent> <buffer> d :py zimvimki.cmd("diff")<CR>')
else:
print >>sys.stderr, 'ZimVimKi Error: No revisions found for page: %s' % wp
except zimwikiclient.ZimWikiXMLRPCError, err:
print >>sys.stderr, 'ZimVimKi XML-RPC Error: %s' % err
def backlinks(self, wp=''):
"""
Display backlinks for a certain page if any.
"""
if self.diffmode:
self.diff_close()
if not wp or wp[-1] == ':':
return
try:
self.focus(2)
vim.command('silent! buffer! ' + self.buffers['backlinks'].num)
vim.command('setlocal modifiable')
blinks = self.xmlrpc.backlinks(wp)
if len(blinks) > 0:
for link in blinks:
self.buffers['backlinks'].buf[:] = map(str, blinks)
vim.command('map <buffer> <enter> :py zimvimki.cmd("edit")<CR>')
else:
print >>sys.stderr, 'ZimVimKi Error: No backlinks found for page: %s' % wp
vim.command('setlocal nomodifiable')
except zimwikiclient.ZimWikiXMLRPCError, err:
print >>sys.stderr, 'ZimVimKi XML-RPC Error: %s' % err
def search(self, type='', pattern=''):
"""
Search the page list for matching pages and display them for editing.
"""
if self.diffmode:
self.diff_close()
self.focus(2)
try:
if type == 'page':
vim.command('silent! buffer! ' + self.buffers['search'].num)
vim.command('setlocal modifiable')
if pattern:
p = re.compile(pattern)
result = filter(p.search, self.pages)
else:
result = self.pages
if len(result) > 0:
self.buffers['search'].buf[:] = result
vim.command('map <buffer> <enter> :py zimvimki.cmd("edit")<CR>')
else:
print >>sys.stderr, 'ZimVimKi Error: No matching pages found!'
elif type == 'media':
vim.command('silent! buffer! ' + self.buffers['media'].num)
vim.command('setlocal modifiable')
if pattern:
p = re.compile(pattern)
result = filter(p.search, self.media)
else:
result = self.media
if len(result) > 0:
self.buffers['media'].buf[:] = result
else:
print >>sys.stderr, 'ZimVimKi Error: No matching media files found!'
vim.command('setlocal nomodifiable')
except:
pass
def close(self, bang):
"""
Closes the current buffer. Works only if the current buffer is a wiki
page. The buffer is also removed from the buffer stack.
"""
if self.diffmode:
self.diff_close()
return
try:
buffer = vim.current.buffer.name.rsplit('/', 1)[1]
if self.buffers[buffer].iswp:
if not bang and self.ismodified(buffer):
print >>sys.stderr, "Warning: %s contains unsaved changes! Use ZWclose!." % buffer
return
vim.command('bp!')
vim.command('bdel! ' + self.buffers[buffer].num)
if self.buffers[buffer].type == 'acwrite':
self.unlock(buffer)
del self.buffers[buffer]
else:
print >>sys.stderr, 'You cannot close special buffer "%s"!' % buffer
except KeyError, err:
print >>sys.stderr, 'You cannot use ZWclose on non wiki page "%s"!' % buffer
def quit(self, bang):
"""
Quits the current session.
"""
unsaved = []
for buffer in self.buffers.keys():
if self.buffers[buffer].iswp:
if not self.ismodified(buffer):
vim.command('silent! buffer! ' + self.buffers[buffer].num)
self.close(False)
elif self.ismodified(buffer) and bang:
vim.command('silent! buffer! ' + self.buffers[buffer].num)
self.close(True)
else:
unsaved.append(buffer)
if len(unsaved) == 0:
vim.command('silent! quitall')
else:
print >>sys.stderr, "Some buffers contain unsaved changes. Use ZWquit! if you really want to quit."
def help(self):
"""
Shows the plugin help.
"""
if self.diffmode:
self.diff_close()
self.focus(2)
vim.command('silent! buffer! ' + self.buffers['help'].num)
vim.command('silent! set buftype=help')
# generate help tags just in case
vim.command('helptags ~/.vim/doc')
vim.command('help zimvimki')
vim.command("setlocal statusline=%{'[help]'}")
def ismodified(self, buffer):
"""
Checks whether the current buffer or a given buffer is modified or not.
"""
if self.buffers[buffer].need_save:
return True
elif "\n".join(self.buffers[buffer].page).strip() != "\n".join(self.buffers[buffer].buf).strip():
return True
else:
return False
def rev_edit(self):
"""
Special mapping for editing revisions from the revisions listing.
"""
row, col = vim.current.window.cursor
wp = vim.current.buffer[row-1].split("\t")[0].strip()
rev = vim.current.buffer[row-1].split("\t")[2].strip()
self.edit(wp, rev)
def focus(self, winnr):
"""
Convenience function to switch the current window focus.
"""
if int(vim.eval('winnr()')) != winnr:
vim.command(str(winnr) + 'wincmd w')
def refresh(self):
"""
Refreshes the page index by retrieving a fresh list of all pages on the
remote server and updating the completion dictionary.
"""
self.pages = []
self.media = []
try:
print >>sys.stdout, "Refreshing page index!"
data = self.xmlrpc.all_pages()
if data:
for page in data:
page = page['id'].encode('utf-8')
ns = page.rsplit(':', 1)[0] + ':'
self.pages.append(page)
if not ns in self.pages:
self.pages.append(ns)
self.media.append(ns)
self.pages.sort()
vim.command('let g:pages = "' + " ".join(self.pages) + '"')
print >>sys.stdout, "Refreshing media index!"
data = self.xmlrpc.list_files(':', True)
if data:
for media in data:
self.media.append(media['id'].encode('utf-8'))
self.media.sort()
vim.command('let g:media = "' + " ".join(self.media) + '"')
except zimwikiclient.ZimWikiXMLRPCError, err:
print >>sys.stderr, "Failed to fetch page list. Please check your configuration\n%s" % err
def lock(self, wp):
"""
Tries to obtain a lock given wiki page.
"""
locks = {}
locks['lock'] = [ wp ]
locks['unlock'] = []
result = self.set_locks(locks)
if locks['lock'] == result['locked']:
print >>sys.stdout, "Locked page %s for editing." % wp
return True
else:
print >>sys.stderr, 'The page "%s" appears to be locked for editing. You have to wait until the lock expires.' % wp
return False
def unlock(self, wp):
"""
Tries to unlock a given wiki page.
"""
locks = {}
locks['lock'] = []
locks['unlock'] = [ wp ]
result = self.set_locks(locks)
if locks['unlock'] == result['unlocked']:
return True
else:
return False
def set_locks(self, locks):
"""
Locks unlocks a given set of pages.
"""
try:
return self.xmlrpc.set_locks(locks)
except zimwikiclient.ZimWikiXMLRPCError, err:
print >>sys.stderr, err
def id_lookup(self):
"""
When editing pages, hiting enter while over a wiki link will open the
page. This functions tries to guess the correct wiki page.
"""
line = vim.current.line
row, col = vim.current.window.cursor
# get namespace from current page
wp = vim.current.buffer.name.rsplit('/', 1)[1]
ns = wp.rsplit(':', 1)[0]
if ns == wp:
ns = ''
# look for link syntax on the left and right from the current curser position
reL = re.compile('\[{2}[^]]*$') # opening link syntax
reR = re.compile('^[^\[]*]{2}') # closing link syntax
L = reL.search(line[:col])
R = reR.search(line[col:])
# if both matched we probably have a link
if L and R:
# sanitize match remove anchors and everything after '|'
id = (L.group() + R.group()).strip('[]').split('|')[0].split('#')[0]
# check if it's not and external/interwiki/share link
if id.find('>') == -1 and id.find('://') == -1 and id.find('\\') == -1:
# check if useshlash is used
if id.find('/'):
id = id.replace('/', ':')
# this is _almost_ a rip off of ZimWikis resolve_id() function
if id[0] == '.':
re_sanitize = re.compile('(\.(?=[^:\.]))')
id = re_sanitize.sub('.:', id)
id = ns + ':' + id
path = id.split(':')
result = []
for dir in path:
if dir == '..':
try:
if result[-1] == '..':
result.append('..')
elif not result.pop():
result.append('..')
except IndexError:
pass
elif dir and dir != '.' and not len(dir.split('.')) > 2:
result.append(dir)
id = ':'.join(result)
elif ns and id[0] != ':' and id.find(':', 0) == -1:
id = ns + ':' + id
# we're done, open the page for editing
print >>sys.stdout, id
self.edit(id)
def cmd(self, cmd):
"""
Callback function to provides various functionality for the page index
(like open namespaces or triggering edit showing backlinks etc).
"""
row, col = vim.current.window.cursor
line = vim.current.buffer[row-1]
# first line triggers nothing in index buffer
if row == 1 and line.find('ns: ') != -1:
return
if line.find('..') == -1:
if line.find('/') == -1:
if not line:
print >>sys.stdout, "meh"
else:
line = self.cur_ns + line
else:
line = self.cur_ns + line.replace('/', ':')
else:
line = self.cur_ns.rsplit(':', 2)[0] + ':'
if line == ":" or line == self.cur_ns:
line = ''
callback = getattr(self, cmd)
callback(line)
def buffer_enter(self, wp):
"""
Loads the buffer on enter.
"""
self.buffers[wp].buf[:] = self.buffers[wp].page
vim.command('setlocal nomodified')
self.buffer_setup()
def buffer_leave(self, wp):
if "\n".join(self.buffers[wp].buf).strip() != "\n".join(self.buffers[wp].page).strip():
self.buffers[wp].page[:] = self.buffers[wp].buf
self.buffers[wp].need_save = True
def buffer_setup(self):
"""
Setup edit environment.
"""
vim.command('setlocal textwidth=0')
vim.command('setlocal wrap')
vim.command('setlocal linebreak')
vim.command('setlocal syntax=zimuwiki')
vim.command('setlocal filetype=zimuwiki')
vim.command('setlocal tabstop=2')
vim.command('setlocal expandtab')
vim.command('setlocal shiftwidth=2')
vim.command('setlocal encoding=utf-8')
vim.command('setlocal completefunc=InsertModeComplete')
vim.command('setlocal omnifunc=InsertModeComplete')
vim.command('map <buffer> <silent> e :py zimvimki.id_lookup()<CR>')
vim.command('imap <buffer> <silent> <C-D><C-B> ****<ESC>1hi')
vim.command('imap <buffer> <silent> <C-D><C-I> ////<ESC>1hi')
vim.command('imap <buffer> <silent> <C-D><C-U> ____<ESC>1hi')
vim.command('imap <buffer> <silent> <C-D><C-L> [[]]<ESC>1hi')
vim.command('imap <buffer> <silent> <C-D><C-M> {{}}<ESC>1hi')
vim.command('imap <buffer> <silent> <C-D><C-K> <code><CR><CR></code><ESC>ki')
vim.command('imap <buffer> <silent> <C-D><C-F> <file><CR><CR></file><ESC>ki')
vim.command('imap <buffer> <silent> <expr> <C-D><C-H> Headline()')
vim.command('imap <buffer> <silent> <expr> <C-D><C-P> SetLvl(+1)')
vim.command('imap <buffer> <silent> <expr> <C-D><C-D> SetLvl(-1)')
class Buffer:
"""
Representates a vim buffer object. Used to manage keep track of all opened
pages and to handle the zimvimki special buffers.
self.num = buffer number (starts at 1)
self.id = buffer id (starts at 0)
self.buf = vim buffer object
self.name = buffer name
self.iswp = True if buffer represents a wiki page
"""
id = None
num = None
name = None
buf = None
def __init__(self, name, type, iswp=False):
"""
Instanziates a new buffer.
"""
vim.command('badd ' + name)
self.num = vim.eval('bufnr("' + name + '")')
self.id = int(self.num) - 1
self.buf = vim.buffers[self.id]
self.name = name
self.iswp = iswp
self.type = type
self.page = []
vim.command('silent! buffer! ' + self.num)
vim.command('setlocal buftype=' + type)
vim.command('abbr <silent> close ZWclose')
vim.command('abbr <silent> close! ZWclose!')
vim.command('abbr <silent> quit ZWquit')
vim.command('abbr <silent> quit! ZWquit!')
vim.command('abbr <silent> q ZWquit')
vim.command('abbr <silent> q! ZWquit!')
vim.command('abbr <silent> qa ZWquit')
vim.command('abbr <silent> qa! ZWquit!')
if type == 'nofile':
vim.command('setlocal nobuflisted')
vim.command('setlocal nomodifiable')
vim.command('setlocal noswapfile')
vim.command("setlocal statusline=%{'[" + self.name + "]'}")
if type == 'acwrite':
self.diff = {}
self.need_save = False
vim.command('autocmd! BufEnter <buffer> py zimvimki.buffer_enter("' + self.name + '")')
vim.command('autocmd! BufLeave <buffer> py zimvimki.buffer_leave("' + self.name + '")')
vim.command("setlocal statusline=%{'[wp]\ " + self.name + "'}\ %r\ [%c,%l][%p]")
if type == 'nowrite':
self.diff = {}
vim.command("setlocal statusline=%{'[wp]\ " + self.name + "'}\ %r\ [%c,%l][%p%%]")
def zimvimki():
"""
Creates the global zimvimki instance.
"""
global zimvimki
zimvimki = ZimVimKi()
EOF
else
command! -nargs=0 ZimVimKi echoerr "ZimVimKi disabled! Python support missing or vim version not supported."
endif
" vim:ts=4:sw=4:et:
*zimvimki* Plugin for editing DokuWiki pages via XML-RPC for Vim > 6.0
For Vim > 7.0
By Michael Klier
<chi@xxxxxxxxxxx>
*zimvimki-plugin*
------------------------------------------------------------------------------
OVERVIEW *zimvimki-overview*
|zimvimki-installation| Installation instructions
|zimvimki-configuration| How to configure zimvimki
|zimvimki-commands| Brief description of the available commands
|zimvimki-buffer-mappings| Description of the mappings available in the
special buffers
|zimvimki-bugs| Bug reports are always welcome ;-)
------------------------------------------------------------------------------
UPDATES *zimvimki-updates*
The official releases can be found at:
git: http://github.com/chimeric/zimvimki
------------------------------------------------------------------------------
INSTALLATION *zimvimki-installation*
Just unpack the tarball in your ~/.vim/ directory. Then edit your .vimrc and
add your settings (see CONFIGURATION). You'll also need to install the python
xmlrpclib module and the dokuwikixmlrpc module in order to use this plugin!
For details about installing those please refer to the documentation specific
for your OS.
------------------------------------------------------------------------------
CONFIGURATION *zimvimki-configuration*
The following variables have to be present in your ~/.vimrc in order to get
DokuVimKi working.
g:DokuVimKi_USER The username used to login into the remote wiki.
g:DokuVimKi_PASS The password used to login into the remote wiki.
g:DokuVimKi_URL The URL of the remote wiki (no trailing slash!).
g:DokuVimKi_INDEX_WINWIDTH The width of the index window (default 30).
g:DokuVimKi_DEFAULT_SUM Default summary used if no summary is given on
save. Defaults to [xmlrpc zimvimki edit].
If you save pages using :w this is used as well
and will result in a minor edit.
------------------------------------------------------------------------------
COMMANDS *zimvimki-commands*
:DWedit <page> Opens the given wiki page in the edit buffer. If
the page does not exist on the remote wiki it will
be created once you issue :DWSave. You can use
<TAB> to autocomplete pages. If the page doesn't
contain any ':' the page will be created in the
current namespace the index is showing.
:DWcd <namespace> Change into a given namespace.
:DWsave <summary> Save the wiki page in the edit buffer to the
remote wiki. If no edit summary is given it
will be saved as minor edit. You can also use :w
but it will not allow to specify a edit summary.
:DWbackLinks <page> Loads a list of pages which link back to the given
wiki page into the edit buffer. If you are already
editing a page you can use the command without
supplying a wiki page and it will load a list of
backlinks to the page loaded in the edit buffer.
You can use <TAB> to autocomplete pages.
:DWrevisions <page> N Lists the available revisions of a wiki page. You
can use an offset (integer) to view earlier
revisions. The number of shown revisions depends
on the $conf['recent'] setting of the remote wiki.
You can use <TAB> to autocomplete pages.
:DWsearch <pattern> Searches for matching pages. You can use regular
expressions!
:DWmediasearch <pattern> Searches for matching media files. You can use
regular expressions.
:DWchanges <timeframe> Lists the recent changes of the remote wiki.
You can specify a timeframe:
Nd show changes of the last N days
Nw show changes of the last N weeks
:DWclose Closes the current edit buffer (removing edit
:DWclose! locks on the remote wiki etc.) - if the buffer
contains changes which haven't been synced back
to the remote wiki this command will issue a
warning. You can also use :close which is setup
as abbreviation.
:DWdiffclose Closes diff mode
:DWupload <file> Allows to upload a file in the current namespace.
:DWupload! <file>
:DWquit Quits the current session and quits vim. This will
:DWquit! fail if there are unsaved changes.
:DWhelp Displays the DokuVimKi help.
------------------------------------------------------------------------------
EDIT-MAPPINGS *zimvimki-edit-mappings*
DokuVimKi mimics the functionality of DokuWikis edit toolbar to make it easier
to insert/edit wiki syntax. Unless otherwise noted all those mappings work
only in insert mode.
<C-D><C-B> inserts bold syntax
<C-D><C-I> inserts italic syntax
<C-D><C-U> inserts underline syntax
<C-D><C-L> inserts link syntax
<C-D><C-M> inserts media syntax
<C-D><C-K> inserts code block syntax
<C-D><C-F> inserts file block syntax
<C-D><C-H> inserts a headline
<C-I><C-P> increases the current headline level by one
<C-I><C-D> decreases the current headline level by one
e opens a link under the current cursor position for editing
(this mappings only works in normal mode)
------------------------------------------------------------------------------
BUFFER-MAPPINGS *zimvimki-buffer-mappings*
DokuVimKi comes with some specials mappings you can use in the special buffers
like the index or the recent changes view.
INDEX
<ENTER> Opens the page for editing, or lists the contents of the
namespace under the cursor.
b Shows a list of the page linking back to the page under the
cursor.
r Shows the revisions of page under the cursor.
REVISIONS
<ENTER> Opens the page revision for editing.
d Opens the diff view for the page and the revision under the
cursor.
CHANGES
<ENTER> Opens the page revision under the cursor for editing.
SEARCH
<ENTER> Opens the page under the cursor for editing.
BACKLINKS
<ENTER> Opens the page under the cursor for editing.
------------------------------------------------------------------------------
BUGS *zimvimki-bugs*
Please use the official bug tracker for feature requests of bug reports:
>
http://github.com/chimeric/zimvimki/issus
If the bug is reproducible, then it will be of great help if a short
description of the events leading to the bug are also given ;-).
vim:tw=78:et:ts=4:ft=help:norl:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# Zim client with API that is compatible with dokuwikixmlrpc.py
# Copyright 2012 Jaap Karssenberg <jaap.karssenberg@xxxxxxxxx>
# Copyright 2008 by Michael Klier <chi@xxxxxxxxxxx>
# This code is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License version 2 only, as published by
# the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
# details (a copy is included in the LICENSE file that accompanied this code).
#
# You should have received a copy of the GNU General Public License version 3
# along with dokuwikixmlrpc. If not, see <http://www.gnu.org/licenses/gpl-2.0.html>
# for a copy of the GPLv2 License.
# TODO
# allow to overwrite useragent?
import StringIO
import zim
from zim.errors import Error
READ = 1
WRITE = 2
CREATE = 4
class ZimWikiError(Exception):
"""ZimWikiError base class."""
pass
class ZimWikiXMLRPCError(ZimWikiError):
"""Triggered on XMLRPC faults."""
def __init__(self, obj):
"""Initalize and call anchestor __init__()."""
ZimWikiError.__init__(self)
if isinstance(obj, xmlrpclib.Fault):
self.page_id = obj.faultCode
self.message = obj.faultString
else:
self.page_id = 0
self.message = obj
def __str__(self):
"""Format returned error message."""
return '<%s %s: \'%s\'>' % (self.__class__.__name__,
self.page_id,
self.message)
class ZimWikiClient(object):
# Incompatibilities:
# - In dokywiki version revisions are of type 'int', we use strings for identifiers
# background is that not all backends have integer revision IDs
# - In links() we only list internal links
# TODO revisions not yet supported - need to hooks versioncontrol plugin
def __init__(self, notebook):
self.interface = zim.NotebookInterface(notebook)
self.notebook = self.interface.notebook
self.notebook.index.update()
def rpc_version_supported(self):
return zim.__version__
def _get_page(self, name):
path = self.notebook.resolve_path(name)
page = self.notebook.get_page(path)
assert hasattr(page, 'source') and page.source
return page
def page(self, page_id, revision=None):
"""Return the raw Wiki text of a given Wiki page.
Optionally return the information of a Wiki page version (see
page_versions())
"""
page = self._get_page(page_id)
if revision:
assert False, 'TODO, versioncontrol'
else:
return page.source.read()
def page_versions(self, page_id, offset=0):
"""Return a list of available versions for a Wiki page."""
assert False, 'TODO, versioncontrol'
# we get list of
# (rev, data, user, msg)
#
# needs to return list of
# {
# 'user': # user that made the change
# 'ip': # ip adres of the user
# 'type': #type of change
# 'sum': # summary of change - first line of msg ?
# 'modified': # UTC tiemstamp
# 'version': # page version timestamp
# }
def page_info(self, page_id, revision=None):
"""Return information about a given Wiki page.
Optionally return the information of a Wiki page version (see
page_versions())
"""
page = self._get_page(page_id)
if revision:
assert False, 'TODO, versioncontrol'
else:
info = {
'name': page.name, # basename ?
'lastModified': 0, # FIXME UTC timestamp
'author': '',
'version': '',
}
return info
def page_html(self, page_id, revision=None):
"""Return the (X)HTML body of a Wiki page.
Optionally return the (X)HTML body of a given Wiki page version (see
page_versions())
"""
page = self._get_page(page_id)
if revision:
assert False, 'TODO, versioncontrol'
else:
exporter = zim.exporter.Exporter(self.notebook, 'html', template=None)
fh = StringIO.StringIO()
exporter.export_page_to_fh(fh, page)
return fh.getvalue()
def put_page(self, page_id, text, summary='', minor=False):
"""Send a Wiki page to the remote Wiki.
Keyword arguments:
page_id -- valpage_id Wiki page page_id
text -- raw Wiki text (UTF-8 encoded)
sum -- summary
minor -- mark as minor edit
"""
page = self._get_page(page_id)
page.parse(text, 'wiki')
self.notebook.store_page(page)
def pagelist(self, namespace):
"""Lists all pages within a given namespace."""
path = self.notebook.resolve_path(namespace)
return self._page_list(self.notebook.get_pagelist(path))
def all_pages(self):
"""List all pages of the remote Wiki."""
return self._page_list(self.notebook.walk())
def _page_list(self, pages):
pageinfo = []
for page in pages:
pageinfo.append({
'id': page.name, # id of the page
'perms': self._permissions(page), # integer denoting the permissions on the page
'size': 0, # FIXME size in bytes
'lastModified': 0, # FIXME dateTime object of last modification date
})
return pageinfo
def backlinks(self, page_id):
"""Return a list of pages that link back to a Wiki page."""
# FIXME Looks like this should be list of names, although expected
# same as for links() -- double check
from zim.index import LINK_DIR_BACKWARD
links = []
path = self.notebook.resolve_path(page_id)
for link in self.notebook.index.list_links(path, LINK_DIR_BACKWARD):
links.append(link.source.name)
return links
def links(self, page_id):
"""Return a list of links contained in a Wiki page."""
links = []
path = self.notebook.resolve_path(page_id)
for link in self.notebook.index.list_links(path):
links.append({
'type': 'local', # local/extern
'page': link.href.name, # the wiki page (or the complete URL if extern)
'href': None, # the complete URL - FIXME ?
})
return links
def recent_changes(self, timestamp):
"""Return the recent changes since a given timestampe (UTC)."""
# return list of
# {
# 'name' # page id
# 'lastModified' # modification date as UTC timestamp
# 'author' # author
# 'version' # page version as timestamp
# }
return [] # TODO
def acl_check(self, page_id):
"""Return the permissions of a Wiki page."""
# Returns integer combination of READ | WRITE | CREATE
page = self._get_page(page_id)
return self._permissions(page)
def _permissions(self, page):
if self.notebook.readonly or page.readonly:
return READ
else:
return READ | WRITE | CREATE
def get_file(self, file_id):
"""Download a file from a remote Wiki."""
pass # TODO
def put_file(self, file_id, data, overwrite = False):
"""Upload a file to a remote Wiki."""
pass # TODO
def delete_file(self, file_id):
"""Delete a file from a remote wiki."""
pass # TODO
def file_info(self, file_id):
"""Return information about a given file."""
pass # TODO
def list_files(self, namespace, recursive = False, pattern = None):
"""List files in a Wiki namespace."""
pass # TODO
def set_locks(self, locks):
"""
Lock/unlock a set of files. Locks must be a dictionary which contains
list of ids to lock/unlock:
locks = { 'lock' : [], 'unlock' : [] }
"""
# Zim does not support this mechanism, so fake it to
# always agree to what is asked
return {
'locked': locks['lock'],
'unlocked': locks['unlock'],
'lockfail': [],
'unlockfail': [],
}
class Callback(object):
"""Callback class used by the option parser.
Instantiates a new ZimWikiClient. It retrieves and outputs the data for
the specified callback. The callback is specified in the option parser. The
option destination has to match a ZimWikiClient method.
"""
def __init__(self, option, opt_str, value, parser):
"""Initalize callback object."""
if parser.values.wiki:
try:
self.zimwiki = ZimWikiClient(parser.values.wiki)
except Error, error:
parser.error(error)
self._parser = parser
(data, output_format) = self.dispatch(option.dest)
if data:
if output_format == 'plain':
print data
elif output_format == 'list':
for item in data:
print item
elif output_format == 'dict':
if type(data) == type([]):
for item in data:
for key in item.keys():
print '%s: %s' % (key, item[key])
print "\n"
else:
for key in data.keys():
print '%s: %s' % (key, data[key])
else:
parser.print_usage()
def _get_page_id(self):
"""Check if the additional arguments contain a Wiki page id."""
try:
return self._parser.rargs.pop()
except IndexError:
self._parser.error('You have to specify a Wiki page.')
def dispatch(self, option):
"""Dispatch the provided callback."""
callback = self.zimwiki.__getattribute__(option)
if option == 'page' or option == 'page_html':
page_id = self._get_page_id()
timestamp = self._parser.values.timestamp
if not timestamp:
return (callback(page_id), 'plain')
else:
return (callback(page_id, timestamp), 'plain')
elif option == 'backlinks':
page_id = self._get_page_id()
return (callback(page_id), 'list')
elif option == 'page_info' or option == 'page_versions' or option == 'links':
page_id = self._get_page_id()
return (callback(page_id), 'dict')
elif option == 'all_pages':
return (callback(), 'list')
elif option == 'recent_changes':
from time import time
timestamp = self._parser.values.timestamp
if not timestamp:
timestamp = int(time())
return (callback(timestamp), 'dict')
def main():
"""Main function. Invoked when called as script.
The module can also be used as simple command line client to query a remote
Wiki. It provides all methods supported by ZimWikis XML-RPC interface. The
retrieved data is slightly formatted when output.
"""
from optparse import OptionParser
parser = OptionParser(version = '%prog ' + zim.__version__)
#parser.set_usage('%prog -u <username> -w <wikiurl> -p <passwd> [options] [wiki:page]')
parser.set_usage('%prog -w <wikiurl> [options] [wiki:page]')
#parser.add_option('-u', '--user',
# dest = 'user',
# help = 'Username to use when authenticating at the remote Wiki.')
parser.add_option('-w', '--wiki',
dest = 'wiki',
help = 'The remote wiki.')
#parser.add_option('-p', '--passwd',
# dest = 'passwd',
# help = 'The user password.')
parser.add_option('--raw',
dest = 'page',
action = 'callback',
callback = Callback,
help = 'Return the raw Wiki text of a Wiki page.')
parser.add_option('--html',
dest = 'page_html',
action = 'callback',
callback = Callback,
help = 'Return the HTML body of a Wiki page.')
parser.add_option('--info',
dest = 'page_info',
action = 'callback',
callback = Callback,
help = 'Return some information about a Wiki page.')
#parser.add_option('--changes',
# dest = 'recent_changes',
# action = 'callback',
# callback = Callback,
# help = 'List recent changes of the Wiki since timestamp.')
parser.add_option('--revisions',
dest = 'page_versions',
action = 'callback',
callback = Callback,
help = 'Liste page revisions since timestamp.')
parser.add_option('--backlinks',
dest = 'backlinks',
action = 'callback',
callback = Callback,
help = 'Return a list of pages that link back to a Wiki page.')
parser.add_option('--allpages',
dest = 'all_pages',
action = 'callback',
callback = Callback,
help = 'List all pages in the remote Wiki.')
parser.add_option('--links',
dest = 'links',
action = 'callback',
callback = Callback,
help = 'Return a list of links contained in a Wiki page.')
parser.add_option('--time',
dest = 'timestamp',
type = 'int',
help = 'Revision timestamp.')
#parser.add_option('--http-basic-auth',
# dest = 'http_basic_auth',
# action = 'store_true',
# help = 'Use HTTP Basic Authentication.',
# default=False)
parser.parse_args()
if __name__ == '__main__':
main()
References
-
CLI?
From: John Geoffrey, 2012-10-22
-
Re: CLI?
From: Jaap Karssenberg, 2012-10-23
-
Re: CLI?
From: Jaap Karssenberg, 2012-10-24
-
Re: CLI?
From: Svenn Are Bjerkem, 2012-10-25
-
Re: CLI?
From: Jaap Karssenberg, 2012-10-26
-
Re: CLI?
From: Jaap Karssenberg, 2012-11-07
-
Re: CLI?
From: Svenn Are Bjerkem, 2012-11-11
-
Re: CLI?
From: Svenn Are Bjerkem, 2012-11-11