lib/soywiki.vim in soywiki-0.0.1 vs lib/soywiki.vim in soywiki-0.0.2
- old
+ new
@@ -1,18 +1,19 @@
" Vim script that turns Vim into a personal wiki
" Maintainer: Daniel Choi <dhchoi@gmail.com>
" License: MIT License (c) 2011 Daniel Choi
-" this matched namedspaced WikiWords, top-level WikiWords, and relative .WikiWords in a
-" namespace
-let s:wiki_link_pattern = '\C\<\([a-z]\+\.\)\?[A-Z][a-z]\+[A-Z]\w*\>\|\.[A-Z][a-z]\+[A-Z]\w*\>'
+" This regex matches namedspaced WikiWords, top-level WikiWords, and relative
+" .WikiWords in a namespace
+let s:wiki_link_pattern = '\C\<\([a-z][[:alnum:]_]\+\.\)\?[A-Z][a-z]\+[A-Z]\w*\>\|\.[A-Z][a-z]\+[A-Z]\w*\>'
let s:rename_links_command = 'soywiki-rename '
let s:find_pages_linking_in_command = 'soywiki-pages-linking-in '
+let s:expand_command = 'soywiki-expand '
+let s:ls_command = 'soywiki-ls-t '
let s:search_for_link = ""
-
func! s:trimString(string)
let string = substitute(a:string, '\s\+$', '', '')
return substitute(string, '^\s\+', '', '')
endfunc
@@ -32,33 +33,46 @@
else
return a:page_title
endif
endfunc
+func! s:namespace_of_title(page_title)
+ if len(split(a:page_title, '\.')) == 2
+ return get(split(a:page_title, '\.'), 0)
+ else
+ ""
+ endif
+endfunc
+
+
func! s:is_wiki_page()
- let title_line = getline(1)
- return (match(title_line, s:wiki_link_pattern) == 0)
+ return (match(getline(1), s:wiki_link_pattern) == 0)
endfunc
-func! s:save_page()
-" write
+
+func! s:page_title2file(page)
+ return substitute(a:page, '\.', '/', 'g')
endfunc
+func! s:filename2pagetitle(page)
+ return substitute(a:page, '/', '.', 'g')
+endfunc
+
func! s:list_pages()
let s:search_for_link = ""
call s:get_page_list()
call s:page_list_window("CompletePageInSelectionWindow", "Select page: ")
endfunc
func! s:link_under_cursor()
let link = expand("<cWORD>")
+ " strip off non-letters at the end (e.g., a comma)
let link = substitute(link, '[^[:alnum:]]*$', '', '')
- " see if he have a namespaced link
+ " see if we have a link relative to the namespace
if (match(link, '^\.')) == 0
" find the namespace from the page title
- let link = s:page_namespace() . link
+ let link = s:page_namespace() . link " this link already has a period at the beginning
endif
-
let link = substitute(link, '^[^\.[:alnum:]]', '', '') " link may begin with period
return link
endfunc
" follows a camel case link to a new page
@@ -87,41 +101,58 @@
end
return s:link_under_cursor()
endfunc
func! s:load_page(page, split)
- let page = a:page
if (s:is_wiki_page())
write
endif
- if (!filereadable(page))
+
+ let file = s:page_title2file(a:page)
+
+ if (!filereadable(file))
" create the file
- call writefile([a:page, '', ''], page)
+ let namespace = s:namespace_of_title(a:page)
+ if len(namespace) > 0
+ call system("mkdir -p " . namespace)
+ endif
+ call writefile([a:page, '', ''], file)
endif
if (a:split == 2)
- exec "vsplit ". page
+ exec "vsplit ". file
else
- exec "split ". page
+ exec "split ". file
endif
if (a:split == 0)
wincmd p
close
endif
+
+ if len(s:search_for_link) > 0
+ let res = search(s:search_for_link, 'cw')
+ let s:search_for_link = ''
+ endif
endfunc
+func! s:load_most_recently_modified_page()
+ let pages = split(system(s:ls_command), "\n")
+ let start_page = len(pages) > 0 ? get(pages, 0) : "HomePage"
+ call s:load_page(start_page, 0)
+endfunc
+
func! s:delete_page()
let file = bufname('%')
let bufnr = bufnr('%')
call delete(file)
call system("git commit " . bufname('%') . " -m 'deletion'")
" go to most recently saved
- " call feedkeys("\<C-o>")
- let target = s:trimString(system("ls -t | head -1"))
+ let target = s:trimString(system(s:ls_command . " | head -1"))
exec "e " . target
exec "bdelete " . bufnr
redraw
echom "Deleted " . file
+ call s:load_most_recently_modified_page()
endfunc
func! s:prompt_for_wiki_word(prompt, default)
let input = s:trimString(input(a:prompt, a:default))
while match(input, s:wiki_link_pattern) == -1
@@ -129,33 +160,38 @@
endwhile
return input
endfunc
func! s:rename_page()
- let file = bufname('%')
- let newname = s:prompt_for_wiki_word("Rename file: ", l:file)
- if (filereadable(newname))
- exe "echom '" . newname . " already exists!'"
+ let oldfile = bufname('%')
+ let newfile = s:page_title2file( s:prompt_for_wiki_word("Rename oldfile: ", l:oldfile) )
+ if (oldfile == newfile)
+ echo "Canceled"
return
endif
- call system("git mv " . l:file . " " . newname)
- exec "e ". newname
+ if (filereadable(newfile))
+ exe "echom '" . newfile . " already exists!'"
+ return
+ endif
+ call system("git mv " . l:oldfile . " " . newfile)
+ exec "e ". newfile
" replace all existing inbound links
" TODO replace this with a ruby script
- call system(s:rename_links_command . file . " " . newname)
+ exec "! " . s:rename_links_command . oldfile . " " . newfile
call system("git commit -am 'rename wiki page'")
e!
endfunc
func! s:create_page()
- let newname = s:prompt_for_wiki_word("New page title: ", "")
- if (filereadable(newname))
- exe "echom '" . newname . " already exists!'"
+ let title = s:prompt_for_wiki_word("New page title: ", "")
+ let newfile = s:page_title2file(title)
+ if (filereadable(newfile))
+ exe "echom '" . newfile . " already exists!'"
return
endif
- call writefile([newname, '', ''], newname)
- exec "e ". newname
+ call writefile([s:filename2pagetitle(title), '', ''], newfile)
+ exec "e ". newfile
endfunc
func! s:save_revision()
call system("git add " . bufname('%'))
call system("git commit " . bufname('%') . " -m 'edit'")
@@ -169,22 +205,22 @@
exec ":!git log --color-words -p " . bufname('%')
end
endfunc
func! s:show_blame()
- exec ":!git blame " . bufname('%')
+ exec ":! git blame --date=relative " . bufname('%')
endfunc
" -------------------------------------------------------------------------------
" select Page
func! s:get_page_list()
if len(bufname('%')) == 0
- let s:page_list = split(system("ls -t"), "\n")
+ let s:page_list = split(system(s:ls_command), "\n")
else
- let s:page_list = split(system("ls -t | grep -vF '" . bufname('%') . "'" ), "\n")
+ let s:page_list = split(system(s:ls_command . " | grep -vF '" . bufname('%') . "'" ), "\n")
endif
endfunction
func! s:pages_in_this_namespace(pages)
let namespace = s:page_namespace()
@@ -214,18 +250,21 @@
return
endif
endfunc
function! s:page_list_window(complete_function, prompt)
+ " remember the original window
+ let s:return_to_winnr = winnr()
topleft split page-list-buffer
setlocal buftype=nofile
setlocal noswapfile
setlocal modifiable
resize 1
inoremap <silent> <buffer> <cr> <Esc>:call <SID>select_page()<CR>
inoremap <buffer> <Tab> <Esc>:call <SID>reduce_matches()<cr>
noremap <buffer> q <Esc>:close<cr>
+ inoremap <buffer> <Esc> <Esc>:close<cr>
exec "setlocal completefunc=" . a:complete_function
" c-p clears the line
call setline(1, a:prompt)
normal $
call feedkeys("a\<c-x>\<c-u>\<c-p>", 't')
@@ -290,25 +329,21 @@
endfun
function! s:select_page()
let page = s:trimString( get(split(getline(line('.')), ": "), 1) )
close
+ exe s:return_to_winnr . "wincmd w"
if (page == '0' || page == '') " no selection
return
end
let match = ""
for item in s:matching_pages
if (item == page)
call s:load_page(page, 0)
-
break
end
endfor
- echo s:search_for_link
- if len(s:search_for_link) > 0
- call search('\<' . s:search_for_link . '\>')
- endif
endfunction
"------------------------------------------------------------------------
" PAGES LINKING IN
"
@@ -317,15 +352,11 @@
func! s:list_pages_linking_in()
let s:pages_linking_in = split(system(s:find_pages_linking_in_command . s:page_title()), "\n")
let s:search_for_link = s:title_without_namespace( s:page_title())
if len(s:pages_linking_in) == 1
- let file = get(s:pages_linking_in, 0)
- write
- exec "e " . file
- " not perfectly targeted but OK for now
- call search(s:search_for_link)
+ call s:load_page(get(s:pages_linking_in, 0), 0)
elseif len(s:pages_linking_in) == 0
echom "No pages link to " . s:page_title() . "!"
else
call s:page_list_window("CompletePagesLinkingIn_InSelectionWindow", "Pages that link to " . s:page_title() . ": ")
endif
@@ -357,20 +388,104 @@
endif
endif
endfun
"------------------------------------------------------------------------
+" This appends the selected text (use visual-mode) to the page selected
+" in the page selection window.
+func! s:extract(...) range
+ if a:0 != 3
+ return s:error("Incorrect number of arguments")
+ endif
+
+ let first = a:firstline
+ let last = a:lastline
+ let file = a:1
+
+ if match(file, s:wiki_link_pattern) == -1
+ echom "Target page must be a WikiWord!"
+ return
+ endif
+
+ let mode = a:2 " append or insert
+ let link = a:3 " replace with link ?
+ let range = first.",".last
+ silent exe range."yank"
+ if link
+ let replacement = s:filename2pagetitle(file)
+ silent exe "norm! :".first.",".last."change\<CR>".replacement."\<CR>.\<CR>"
+ else
+ " this one just deletes the line
+ silent exe "norm! :".first.",".last."change\<CR>.\<CR>"
+ endif
+ if bufnr(file) == -1 || bufwinnr(bufnr(file)) == -1
+ if !filereadable(file)
+ " create the file
+ let page_title = s:filename2pagetitle(file)
+ let namespace = s:namespace_of_title(page_title)
+ if len(namespace) > 0
+ call system("mkdir -p " . namespace)
+ endif
+ call writefile([page_title, '', ''], file)
+ endif
+ exec "split ".file
+ else
+ let targetWindow = bufwinnr(bufnr(file))
+ exe targetWindow."wincmd w"
+ end
+ if mode == 'append'
+ normal G
+ silent put
+ silent put= ''
+ elseif mode == 'insert'
+ call cursor(2, 0)
+ silent put
+ end
+ write!
+endfunc
+
+
+func! s:error(str)
+ echohl ErrorMsg
+ echomsg a:str
+ echohl None
+endfunction
+
+func! s:insert_divider()
+ let divider = '------------------------------------------------------------------------'
+ silent put! =divider
+ silent put=''
+endfunc
+"------------------------------------------------------------------------
+" SEARCH
+func! s:wiki_search(pattern)
+
+ let pattern = (empty(a:pattern) ? @/ : a:pattern)
+ execute printf('vimgrep/%s/ %s', pattern, "**/*")
+endfunc
+
+"------------------------------------------------------------------------
" This opens a new buffer with all the lines with just WikiLinks on them
" expanded (recursively). This is not a wiki buffer but a text buffer
-func! s:unfurl()
- let res = system("soywiki-unfurl " . bufname('%'))
+func! s:expand(seamless)
+ if a:seamless == 1
+ " seamful, the default
+ echom "Expanding seamfully. Please wait."
+ let res = system(s:expand_command . " seamless " . bufname('%'))
+ else " seamless
+ echom "Expanding seamlessly. Please wait."
+ let res = system(s:expand_command . " seamful " . bufname('%'))
+ endif
vertical botright new
setlocal buftype=nofile "scratch buffer for viewing; user can write
- put =res
- 1delete
- normal 1G
+ silent! put =res
+ silent! 1delete
+ silent! normal 1G
+ redraw
+ echom "Expanded " . (a:seamless == 0 ? 'seamfully' : 'seamlessly') . "."
+
endfunc
"------------------------------------------------------------------------
func! s:open_href()
@@ -386,10 +501,17 @@
func! s:global_mappings()
noremap <leader>m :call <SID>list_pages()<CR>
noremap <leader>M :call <SID>list_pages_linking_in()<CR>
noremap <silent> <leader>o :call <SID>open_href()<cr>
+
+ command! -bar -nargs=1 -range -complete=file SWAppend :<line1>,<line2>call s:extract(<f-args>, 'append', 0)
+ command! -bar -nargs=1 -range -complete=file SWInsert :<line1>,<line2>call s:extract(<f-args>, 'insert', 0)
+ command! -bar -nargs=1 -range -complete=file SWLinkAppend :<line1>,<line2>call s:extract(<f-args>, 'append', 1)
+ command! -bar -nargs=1 -range -complete=file SWLinkInsert :<line1>,<line2>call s:extract(<f-args>, 'insert', 1)
+
+ command! -bar -nargs=1 SWSearch :call s:wiki_search(<f-args>)
endfunc
" this checks if the buffer is a SoyWiki file (from firstline)
" and then turns on syntax coloring and mappings as necessary
func! s:prep_buffer()
@@ -397,20 +519,31 @@
set textwidth=72
nnoremap <buffer> <cr> :call <SID>follow_link_under_cursor(0)<cr>
nnoremap <buffer> - :call <SID>follow_link_under_cursor(1)<cr>
nnoremap <buffer> \| :call <SID>follow_link_under_cursor(2)<cr>
noremap <buffer> <leader>f :call <SID>follow_link(0)<CR>
- noremap <buffer> <leader>n :call <SID>find_next_wiki_link(0)<CR>
- noremap <buffer> <leader>p :call <SID>find_next_wiki_link(1)<CR>
+ noremap <buffer> <c-n> :call <SID>find_next_wiki_link(0)<CR>
+ noremap <buffer> <c-p> :call <SID>find_next_wiki_link(1)<CR>
+
noremap <leader>c :call <SID>create_page()<CR>
- command! -buffer SWDelete :call s:delete_page()
command! -buffer SWRename :call s:rename_page()
+
+ noremap <buffer> <leader>r :call <SID>rename_page()<CR>
+ command! -buffer SWDelete :call s:delete_page()
+ noremap <buffer> <leader># :call <SID>delete_page()<CR>
+
command! -buffer SWLog :call s:show_revision_history(0)
noremap <buffer> <leader>l :call <SID>show_revision_history(0)<CR>
command! -buffer SWLogStat :call s:show_revision_history(1)
command! -buffer SWBlame :call s:show_blame()
- noremap <buffer> <leader>x :call <SID>unfurl()<CR>
+ noremap <buffer> <leader>b :call <SID>show_blame()<CR>
+
+
+
+ noremap <buffer> <leader>x :call <SID>expand(0)<CR>
+ noremap <buffer> <leader>X :call <SID>expand(1)<CR>
+
set nu
setlocal completefunc=CompletePage
augroup <buffer>
au!
autocmd BufWritePost <buffer> call s:save_revision()
@@ -426,18 +559,13 @@
endif
endfunc
call s:global_mappings()
-autocmd WinEnter * call s:highlight_wikiwords()
+autocmd BufReadPost,BufNewFile,WinEnter * call s:highlight_wikiwords()
autocmd BufEnter * call s:prep_buffer()
-" load most recent page
-let pages = split(system("ls -t" ), "\n")
-let start_page = len(pages) > 0 ? get(pages, 0) : "HomePage"
-call s:load_page(start_page, 0)
-
if (!isdirectory(".git"))
call system("git init")
echom "Created .git repository to store revisions"
endif
@@ -451,5 +579,14 @@
if !exists("g:SoyWiki#browser_command")
echom "Can't find the to open your web browser."
endif
endif
+if len(bufname("%")) == 0
+ call s:load_most_recently_modified_page()
+else
+ call s:load_page(bufname("%"), 0)
+endif
+
+call s:get_page_list()
+syntax on
+let mapleader = ','