mirror of
https://github.com/gryf/.vim.git
synced 2025-12-17 11:30:29 +01:00
Removed ACP plugin. Found it annoying after a while. Reorganized rst2blogger plugin. Added documentation for it.
This commit is contained in:
@@ -9,7 +9,6 @@ ScriptID SourceID Filename
|
||||
2666 13424 Mark
|
||||
2262 8944 occur.vim
|
||||
910 14349 pydoc.vim
|
||||
1879 11894 AutoComplPop
|
||||
#2421 9423 pysmell.vim
|
||||
152 3342 showmarks.vim
|
||||
2540 11006 snipMate.vim
|
||||
|
||||
431
autoload/acp.vim
431
autoload/acp.vim
@@ -1,431 +0,0 @@
|
||||
"=============================================================================
|
||||
" Copyright (c) 2007-2009 Takeshi NISHIDA
|
||||
"
|
||||
"=============================================================================
|
||||
" LOAD GUARD {{{1
|
||||
|
||||
if exists('g:loaded_autoload_acp') || v:version < 702
|
||||
finish
|
||||
endif
|
||||
let g:loaded_autoload_acp = 1
|
||||
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
" GLOBAL FUNCTIONS: {{{1
|
||||
|
||||
"
|
||||
function acp#enable()
|
||||
call acp#disable()
|
||||
|
||||
augroup AcpGlobalAutoCommand
|
||||
autocmd!
|
||||
autocmd InsertEnter * unlet! s:posLast s:lastUncompletable
|
||||
autocmd InsertLeave * call s:finishPopup(1)
|
||||
augroup END
|
||||
|
||||
if g:acp_mappingDriven
|
||||
call s:mapForMappingDriven()
|
||||
else
|
||||
autocmd AcpGlobalAutoCommand CursorMovedI * call s:feedPopup()
|
||||
endif
|
||||
|
||||
nnoremap <silent> i i<C-r>=<SID>feedPopup()<CR>
|
||||
nnoremap <silent> a a<C-r>=<SID>feedPopup()<CR>
|
||||
nnoremap <silent> R R<C-r>=<SID>feedPopup()<CR>
|
||||
endfunction
|
||||
|
||||
"
|
||||
function acp#disable()
|
||||
call s:unmapForMappingDriven()
|
||||
augroup AcpGlobalAutoCommand
|
||||
autocmd!
|
||||
augroup END
|
||||
nnoremap i <Nop> | nunmap i
|
||||
nnoremap a <Nop> | nunmap a
|
||||
nnoremap R <Nop> | nunmap R
|
||||
endfunction
|
||||
|
||||
"
|
||||
function acp#lock()
|
||||
let s:lockCount += 1
|
||||
endfunction
|
||||
|
||||
"
|
||||
function acp#unlock()
|
||||
let s:lockCount -= 1
|
||||
if s:lockCount < 0
|
||||
let s:lockCount = 0
|
||||
throw "AutoComplPop: not locked"
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
function acp#meetsForSnipmate(context)
|
||||
if g:acp_behaviorSnipmateLength < 0
|
||||
return 0
|
||||
endif
|
||||
let matches = matchlist(a:context, '\(^\|\s\|\<\)\(\u\{' .
|
||||
\ g:acp_behaviorSnipmateLength . ',}\)$')
|
||||
return !empty(matches) && !empty(s:getMatchingSnipItems(matches[2]))
|
||||
endfunction
|
||||
|
||||
"
|
||||
function acp#meetsForKeyword(context)
|
||||
if g:acp_behaviorKeywordLength < 0
|
||||
return 0
|
||||
endif
|
||||
let matches = matchlist(a:context, '\(\k\{' . g:acp_behaviorKeywordLength . ',}\)$')
|
||||
if empty(matches)
|
||||
return 0
|
||||
endif
|
||||
for ignore in g:acp_behaviorKeywordIgnores
|
||||
if stridx(ignore, matches[1]) == 0
|
||||
return 0
|
||||
endif
|
||||
endfor
|
||||
return 1
|
||||
endfunction
|
||||
|
||||
"
|
||||
function acp#meetsForFile(context)
|
||||
if g:acp_behaviorFileLength < 0
|
||||
return 0
|
||||
endif
|
||||
if has('win32') || has('win64')
|
||||
let separator = '[/\\]'
|
||||
else
|
||||
let separator = '\/'
|
||||
endif
|
||||
if a:context !~ '\f' . separator . '\f\{' . g:acp_behaviorFileLength . ',}$'
|
||||
return 0
|
||||
endif
|
||||
return a:context !~ '[*/\\][/\\]\f*$\|[^[:print:]]\f*$'
|
||||
endfunction
|
||||
|
||||
"
|
||||
function acp#meetsForRubyOmni(context)
|
||||
if !has('ruby')
|
||||
return 0
|
||||
endif
|
||||
if g:acp_behaviorRubyOmniMethodLength >= 0 &&
|
||||
\ a:context =~ '[^. \t]\(\.\|::\)\k\{' .
|
||||
\ g:acp_behaviorRubyOmniMethodLength . ',}$'
|
||||
return 1
|
||||
endif
|
||||
if g:acp_behaviorRubyOmniSymbolLength >= 0 &&
|
||||
\ a:context =~ '\(^\|[^:]\):\k\{' .
|
||||
\ g:acp_behaviorRubyOmniSymbolLength . ',}$'
|
||||
return 1
|
||||
endif
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
"
|
||||
function acp#meetsForPythonOmni(context)
|
||||
return has('python') && g:acp_behaviorPythonOmniLength >= 0 &&
|
||||
\ a:context =~ '\k\.\k\{' . g:acp_behaviorPythonOmniLength . ',}$'
|
||||
endfunction
|
||||
|
||||
"
|
||||
function acp#meetsForPerlOmni(context)
|
||||
return g:acp_behaviorPerlOmniLength >= 0 &&
|
||||
\ a:context =~ '\w->\k\{' . g:acp_behaviorPerlOmniLength . ',}$'
|
||||
endfunction
|
||||
|
||||
"
|
||||
function acp#meetsForXmlOmni(context)
|
||||
return g:acp_behaviorXmlOmniLength >= 0 &&
|
||||
\ a:context =~ '\(<\|<\/\|<[^>]\+ \|<[^>]\+=\"\)\k\{' .
|
||||
\ g:acp_behaviorXmlOmniLength . ',}$'
|
||||
endfunction
|
||||
|
||||
"
|
||||
function acp#meetsForHtmlOmni(context)
|
||||
return g:acp_behaviorHtmlOmniLength >= 0 &&
|
||||
\ a:context =~ '\(<\|<\/\|<[^>]\+ \|<[^>]\+=\"\)\k\{' .
|
||||
\ g:acp_behaviorHtmlOmniLength . ',}$'
|
||||
endfunction
|
||||
|
||||
"
|
||||
function acp#meetsForCssOmni(context)
|
||||
if g:acp_behaviorCssOmniPropertyLength >= 0 &&
|
||||
\ a:context =~ '\(^\s\|[;{]\)\s*\k\{' .
|
||||
\ g:acp_behaviorCssOmniPropertyLength . ',}$'
|
||||
return 1
|
||||
endif
|
||||
if g:acp_behaviorCssOmniValueLength >= 0 &&
|
||||
\ a:context =~ '[:@!]\s*\k\{' .
|
||||
\ g:acp_behaviorCssOmniValueLength . ',}$'
|
||||
return 1
|
||||
endif
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
"
|
||||
function acp#completeSnipmate(findstart, base)
|
||||
if a:findstart
|
||||
let s:posSnipmateCompletion = len(matchstr(s:getCurrentText(), '.*\U'))
|
||||
return s:posSnipmateCompletion
|
||||
endif
|
||||
let lenBase = len(a:base)
|
||||
let items = filter(GetSnipsInCurrentScope(),
|
||||
\ 'strpart(v:key, 0, lenBase) ==? a:base')
|
||||
return map(sort(items(items)), 's:makeSnipmateItem(v:val[0], v:val[1])')
|
||||
endfunction
|
||||
|
||||
"
|
||||
function acp#onPopupCloseSnipmate()
|
||||
let word = s:getCurrentText()[s:posSnipmateCompletion :]
|
||||
for trigger in keys(GetSnipsInCurrentScope())
|
||||
if word ==# trigger
|
||||
call feedkeys("\<C-r>=TriggerSnippet()\<CR>", "n")
|
||||
return 0
|
||||
endif
|
||||
endfor
|
||||
return 1
|
||||
endfunction
|
||||
|
||||
"
|
||||
function acp#onPopupPost()
|
||||
" to clear <C-r>= expression on command-line
|
||||
echo ''
|
||||
if pumvisible()
|
||||
inoremap <silent> <expr> <C-h> acp#onBs()
|
||||
inoremap <silent> <expr> <BS> acp#onBs()
|
||||
" a command to restore to original text and select the first match
|
||||
return (s:behavsCurrent[s:iBehavs].command =~# "\<C-p>" ? "\<C-n>\<Up>"
|
||||
\ : "\<C-p>\<Down>")
|
||||
endif
|
||||
let s:iBehavs += 1
|
||||
if len(s:behavsCurrent) > s:iBehavs
|
||||
call s:setCompletefunc()
|
||||
return printf("\<C-e>%s\<C-r>=acp#onPopupPost()\<CR>",
|
||||
\ s:behavsCurrent[s:iBehavs].command)
|
||||
else
|
||||
let s:lastUncompletable = {
|
||||
\ 'word': s:getCurrentWord(),
|
||||
\ 'commands': map(copy(s:behavsCurrent), 'v:val.command')[1:],
|
||||
\ }
|
||||
call s:finishPopup(0)
|
||||
return "\<C-e>"
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
function acp#onBs()
|
||||
" using "matchstr" and not "strpart" in order to handle multi-byte
|
||||
" characters
|
||||
if call(s:behavsCurrent[s:iBehavs].meets,
|
||||
\ [matchstr(s:getCurrentText(), '.*\ze.')])
|
||||
return "\<BS>"
|
||||
endif
|
||||
return "\<C-e>\<BS>"
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
" LOCAL FUNCTIONS: {{{1
|
||||
|
||||
"
|
||||
function s:mapForMappingDriven()
|
||||
call s:unmapForMappingDriven()
|
||||
let s:keysMappingDriven = [
|
||||
\ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||
\ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
\ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
\ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
\ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
\ '-', '_', '~', '^', '.', ',', ':', '!', '#', '=', '%', '$', '@', '<', '>', '/', '\',
|
||||
\ '<Space>', '<C-h>', '<BS>', ]
|
||||
for key in s:keysMappingDriven
|
||||
execute printf('inoremap <silent> %s %s<C-r>=<SID>feedPopup()<CR>',
|
||||
\ key, key)
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
"
|
||||
function s:unmapForMappingDriven()
|
||||
if !exists('s:keysMappingDriven')
|
||||
return
|
||||
endif
|
||||
for key in s:keysMappingDriven
|
||||
execute 'iunmap ' . key
|
||||
endfor
|
||||
let s:keysMappingDriven = []
|
||||
endfunction
|
||||
|
||||
"
|
||||
function s:setTempOption(group, name, value)
|
||||
call extend(s:tempOptionSet[a:group], { a:name : eval('&' . a:name) }, 'keep')
|
||||
execute printf('let &%s = a:value', a:name)
|
||||
endfunction
|
||||
|
||||
"
|
||||
function s:restoreTempOptions(group)
|
||||
for [name, value] in items(s:tempOptionSet[a:group])
|
||||
execute printf('let &%s = value', name)
|
||||
endfor
|
||||
let s:tempOptionSet[a:group] = {}
|
||||
endfunction
|
||||
|
||||
"
|
||||
function s:getCurrentWord()
|
||||
return matchstr(s:getCurrentText(), '\k*$')
|
||||
endfunction
|
||||
|
||||
"
|
||||
function s:getCurrentText()
|
||||
return strpart(getline('.'), 0, col('.') - 1)
|
||||
endfunction
|
||||
|
||||
"
|
||||
function s:getPostText()
|
||||
return strpart(getline('.'), col('.') - 1)
|
||||
endfunction
|
||||
|
||||
"
|
||||
function s:isModifiedSinceLastCall()
|
||||
if exists('s:posLast')
|
||||
let posPrev = s:posLast
|
||||
let nLinesPrev = s:nLinesLast
|
||||
let textPrev = s:textLast
|
||||
endif
|
||||
let s:posLast = getpos('.')
|
||||
let s:nLinesLast = line('$')
|
||||
let s:textLast = getline('.')
|
||||
if !exists('posPrev')
|
||||
return 1
|
||||
elseif posPrev[1] != s:posLast[1] || nLinesPrev != s:nLinesLast
|
||||
return (posPrev[1] - s:posLast[1] == nLinesPrev - s:nLinesLast)
|
||||
elseif textPrev ==# s:textLast
|
||||
return 0
|
||||
elseif posPrev[2] > s:posLast[2]
|
||||
return 1
|
||||
elseif has('gui_running') && has('multi_byte')
|
||||
" NOTE: auto-popup causes a strange behavior when IME/XIM is working
|
||||
return posPrev[2] + 1 == s:posLast[2]
|
||||
endif
|
||||
return posPrev[2] != s:posLast[2]
|
||||
endfunction
|
||||
|
||||
"
|
||||
function s:makeCurrentBehaviorSet()
|
||||
let modified = s:isModifiedSinceLastCall()
|
||||
if exists('s:behavsCurrent[s:iBehavs].repeat') && s:behavsCurrent[s:iBehavs].repeat
|
||||
let behavs = [ s:behavsCurrent[s:iBehavs] ]
|
||||
elseif exists('s:behavsCurrent[s:iBehavs]')
|
||||
return []
|
||||
elseif modified
|
||||
let behavs = copy(exists('g:acp_behavior[&filetype]')
|
||||
\ ? g:acp_behavior[&filetype]
|
||||
\ : g:acp_behavior['*'])
|
||||
else
|
||||
return []
|
||||
endif
|
||||
let text = s:getCurrentText()
|
||||
call filter(behavs, 'call(v:val.meets, [text])')
|
||||
let s:iBehavs = 0
|
||||
if exists('s:lastUncompletable') &&
|
||||
\ stridx(s:getCurrentWord(), s:lastUncompletable.word) == 0 &&
|
||||
\ map(copy(behavs), 'v:val.command') ==# s:lastUncompletable.commands
|
||||
let behavs = []
|
||||
else
|
||||
unlet! s:lastUncompletable
|
||||
endif
|
||||
return behavs
|
||||
endfunction
|
||||
|
||||
"
|
||||
function s:feedPopup()
|
||||
" NOTE: CursorMovedI is not triggered while the popup menu is visible. And
|
||||
" it will be triggered when popup menu is disappeared.
|
||||
if s:lockCount > 0 || pumvisible() || &paste
|
||||
return ''
|
||||
endif
|
||||
if exists('s:behavsCurrent[s:iBehavs].onPopupClose')
|
||||
if !call(s:behavsCurrent[s:iBehavs].onPopupClose, [])
|
||||
call s:finishPopup(1)
|
||||
return ''
|
||||
endif
|
||||
endif
|
||||
let s:behavsCurrent = s:makeCurrentBehaviorSet()
|
||||
if empty(s:behavsCurrent)
|
||||
call s:finishPopup(1)
|
||||
return ''
|
||||
endif
|
||||
" In case of dividing words by symbols (e.g. "for(int", "ab==cd") while a
|
||||
" popup menu is visible, another popup is not available unless input <C-e>
|
||||
" or try popup once. So first completion is duplicated.
|
||||
call insert(s:behavsCurrent, s:behavsCurrent[s:iBehavs])
|
||||
call s:setTempOption(s:GROUP0, 'spell', 0)
|
||||
call s:setTempOption(s:GROUP0, 'completeopt', 'menuone' . (g:acp_completeoptPreview ? ',preview' : ''))
|
||||
call s:setTempOption(s:GROUP0, 'complete', g:acp_completeOption)
|
||||
call s:setTempOption(s:GROUP0, 'ignorecase', g:acp_ignorecaseOption)
|
||||
" NOTE: With CursorMovedI driven, Set 'lazyredraw' to avoid flickering.
|
||||
" With Mapping driven, set 'nolazyredraw' to make a popup menu visible.
|
||||
call s:setTempOption(s:GROUP0, 'lazyredraw', !g:acp_mappingDriven)
|
||||
" NOTE: 'textwidth' must be restored after <C-e>.
|
||||
call s:setTempOption(s:GROUP1, 'textwidth', 0)
|
||||
call s:setCompletefunc()
|
||||
call feedkeys(s:behavsCurrent[s:iBehavs].command . "\<C-r>=acp#onPopupPost()\<CR>", 'n')
|
||||
return '' " this function is called by <C-r>=
|
||||
endfunction
|
||||
|
||||
"
|
||||
function s:finishPopup(fGroup1)
|
||||
inoremap <C-h> <Nop> | iunmap <C-h>
|
||||
inoremap <BS> <Nop> | iunmap <BS>
|
||||
let s:behavsCurrent = []
|
||||
call s:restoreTempOptions(s:GROUP0)
|
||||
if a:fGroup1
|
||||
call s:restoreTempOptions(s:GROUP1)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
function s:setCompletefunc()
|
||||
if exists('s:behavsCurrent[s:iBehavs].completefunc')
|
||||
call s:setTempOption(0, 'completefunc', s:behavsCurrent[s:iBehavs].completefunc)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
function s:makeSnipmateItem(key, snip)
|
||||
if type(a:snip) == type([])
|
||||
let descriptions = map(copy(a:snip), 'v:val[0]')
|
||||
let snipFormatted = '[MULTI] ' . join(descriptions, ', ')
|
||||
else
|
||||
let snipFormatted = substitute(a:snip, '\(\n\|\s\)\+', ' ', 'g')
|
||||
endif
|
||||
return {
|
||||
\ 'word': a:key,
|
||||
\ 'menu': strpart(snipFormatted, 0, 80),
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
"
|
||||
function s:getMatchingSnipItems(base)
|
||||
let key = a:base . "\n"
|
||||
if !exists('s:snipItems[key]')
|
||||
let s:snipItems[key] = items(GetSnipsInCurrentScope())
|
||||
call filter(s:snipItems[key], 'strpart(v:val[0], 0, len(a:base)) ==? a:base')
|
||||
call map(s:snipItems[key], 's:makeSnipmateItem(v:val[0], v:val[1])')
|
||||
endif
|
||||
return s:snipItems[key]
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
" INITIALIZATION {{{1
|
||||
|
||||
let s:GROUP0 = 0
|
||||
let s:GROUP1 = 1
|
||||
let s:lockCount = 0
|
||||
let s:behavsCurrent = []
|
||||
let s:iBehavs = 0
|
||||
let s:tempOptionSet = [{}, {}]
|
||||
let s:snipItems = {}
|
||||
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
" vim: set fdm=marker:
|
||||
512
doc/acp.txt
512
doc/acp.txt
@@ -1,512 +0,0 @@
|
||||
*acp.txt* Automatically opens popup menu for completions.
|
||||
|
||||
Copyright (c) 2007-2009 Takeshi NISHIDA
|
||||
|
||||
AutoComplPop *autocomplpop* *acp*
|
||||
|
||||
INTRODUCTION |acp-introduction|
|
||||
INSTALLATION |acp-installation|
|
||||
USAGE |acp-usage|
|
||||
COMMANDS |acp-commands|
|
||||
OPTIONS |acp-options|
|
||||
SPECIAL THANKS |acp-thanks|
|
||||
CHANGELOG |acp-changelog|
|
||||
ABOUT |acp-about|
|
||||
|
||||
|
||||
==============================================================================
|
||||
INTRODUCTION *acp-introduction*
|
||||
|
||||
With this plugin, your vim comes to automatically opens popup menu for
|
||||
completions when you enter characters or move the cursor in Insert mode. It
|
||||
won't prevent you continuing entering characters.
|
||||
|
||||
|
||||
==============================================================================
|
||||
INSTALLATION *acp-installation*
|
||||
|
||||
Put all files into your runtime directory. If you have the zip file, extract
|
||||
it to your runtime directory.
|
||||
|
||||
You should place the files as follows:
|
||||
>
|
||||
<your runtime directory>/plugin/acp.vim
|
||||
<your runtime directory>/doc/acp.txt
|
||||
...
|
||||
<
|
||||
If you disgust to jumble up this plugin and other plugins in your runtime
|
||||
directory, put the files into new directory and just add the directory path to
|
||||
'runtimepath'. It's easy to uninstall the plugin.
|
||||
|
||||
And then update your help tags files to enable fuzzyfinder help. See
|
||||
|add-local-help| for details.
|
||||
|
||||
|
||||
==============================================================================
|
||||
USAGE *acp-usage*
|
||||
|
||||
Once this plugin is installed, auto-popup is enabled at startup by default.
|
||||
|
||||
Which completion method is used depends on the text before the cursor. The
|
||||
default behavior is as follows:
|
||||
|
||||
kind filetype text before the cursor ~
|
||||
Keyword * two keyword characters
|
||||
Filename * a filename character + a path separator
|
||||
+ 0 or more filename character
|
||||
Omni ruby ".", "::" or non-word character + ":"
|
||||
(|+ruby| required.)
|
||||
Omni python "." (|+python| required.)
|
||||
Omni xml "<", "</" or ("<" + non-">" characters + " ")
|
||||
Omni html/xhtml "<", "</" or ("<" + non-">" characters + " ")
|
||||
Omni css (":", ";", "{", "^", "@", or "!")
|
||||
+ 0 or 1 space
|
||||
|
||||
Also, you can make user-defined completion and snipMate's trigger completion
|
||||
(|acp-snipMate|) auto-popup if the options are set.
|
||||
|
||||
These behavior are customizable.
|
||||
|
||||
*acp-snipMate*
|
||||
snipMate's Trigger Completion ~
|
||||
|
||||
snipMate's trigger completion enables you to complete a snippet trigger
|
||||
provided by snipMate plugin
|
||||
(http://www.vim.org/scripts/script.php?script_id=2540) and expand it.
|
||||
|
||||
|
||||
To enable auto-popup for this completion, add following function to
|
||||
plugin/snipMate.vim:
|
||||
>
|
||||
fun! GetSnipsInCurrentScope()
|
||||
let snips = {}
|
||||
for scope in [bufnr('%')] + split(&ft, '\.') + ['_']
|
||||
call extend(snips, get(s:snippets, scope, {}), 'keep')
|
||||
call extend(snips, get(s:multi_snips, scope, {}), 'keep')
|
||||
endfor
|
||||
return snips
|
||||
endf
|
||||
<
|
||||
And set |g:acp_behaviorSnipmateLength| option to 1.
|
||||
|
||||
There is the restriction on this auto-popup, that the word before cursor must
|
||||
consist only of uppercase characters.
|
||||
|
||||
*acp-perl-omni*
|
||||
Perl Omni-Completion ~
|
||||
|
||||
AutoComplPop supports perl-completion.vim
|
||||
(http://www.vim.org/scripts/script.php?script_id=2852).
|
||||
|
||||
To enable auto-popup for this completion, set |g:acp_behaviorPerlOmniLength|
|
||||
option to 0 or more.
|
||||
|
||||
|
||||
==============================================================================
|
||||
COMMANDS *acp-commands*
|
||||
|
||||
*:AcpEnable*
|
||||
:AcpEnable
|
||||
enables auto-popup.
|
||||
|
||||
*:AcpDisable*
|
||||
:AcpDisable
|
||||
disables auto-popup.
|
||||
|
||||
*:AcpLock*
|
||||
:AcpLock
|
||||
suspends auto-popup temporarily.
|
||||
|
||||
For the purpose of avoiding interruption to another script, it is
|
||||
recommended to insert this command and |:AcpUnlock| than |:AcpDisable|
|
||||
and |:AcpEnable| .
|
||||
|
||||
*:AcpUnlock*
|
||||
:AcpUnlock
|
||||
resumes auto-popup suspended by |:AcpLock| .
|
||||
|
||||
|
||||
==============================================================================
|
||||
OPTIONS *acp-options*
|
||||
|
||||
*g:acp_enableAtStartup* >
|
||||
let g:acp_enableAtStartup = 1
|
||||
<
|
||||
If non-zero, auto-popup is enabled at startup.
|
||||
|
||||
*g:acp_mappingDriven* >
|
||||
let g:acp_mappingDriven = 0
|
||||
<
|
||||
If non-zero, auto-popup is triggered by key mappings instead of
|
||||
|CursorMovedI| event. This is useful to avoid auto-popup by moving
|
||||
cursor in Insert mode.
|
||||
|
||||
*g:acp_ignorecaseOption* >
|
||||
let g:acp_ignorecaseOption = 1
|
||||
<
|
||||
Value set to 'ignorecase' temporarily when auto-popup.
|
||||
|
||||
*g:acp_completeOption* >
|
||||
let g:acp_completeOption = '.,w,b,k'
|
||||
<
|
||||
Value set to 'complete' temporarily when auto-popup.
|
||||
|
||||
*g:acp_completeoptPreview* >
|
||||
let g:acp_completeoptPreview = 0
|
||||
<
|
||||
If non-zero, "preview" is added to 'completeopt' when auto-popup.
|
||||
|
||||
*g:acp_behaviorUserDefinedFunction* >
|
||||
let g:acp_behaviorUserDefinedFunction = ''
|
||||
<
|
||||
|g:acp_behavior-completefunc| for user-defined completion. If empty,
|
||||
this completion will be never attempted.
|
||||
|
||||
*g:acp_behaviorUserDefinedMeets* >
|
||||
let g:acp_behaviorUserDefinedMeets = ''
|
||||
<
|
||||
|g:acp_behavior-meets| for user-defined completion. If empty, this
|
||||
completion will be never attempted.
|
||||
|
||||
*g:acp_behaviorSnipmateLength* >
|
||||
let g:acp_behaviorSnipmateLength = -1
|
||||
<
|
||||
Pattern before the cursor, which are needed to attempt
|
||||
snipMate-trigger completion.
|
||||
|
||||
*g:acp_behaviorKeywordCommand* >
|
||||
let g:acp_behaviorKeywordCommand = "\<C-n>"
|
||||
<
|
||||
Command for keyword completion. This option is usually set "\<C-n>" or
|
||||
"\<C-p>".
|
||||
|
||||
*g:acp_behaviorKeywordLength* >
|
||||
let g:acp_behaviorKeywordLength = 2
|
||||
<
|
||||
Length of keyword characters before the cursor, which are needed to
|
||||
attempt keyword completion. If negative value, this completion will be
|
||||
never attempted.
|
||||
|
||||
*g:acp_behaviorKeywordIgnores* >
|
||||
let g:acp_behaviorKeywordIgnores = []
|
||||
<
|
||||
List of string. If a word before the cursor matches to the front part
|
||||
of one of them, keyword completion won't be attempted.
|
||||
|
||||
E.g., when there are too many keywords beginning with "get" for the
|
||||
completion and auto-popup by entering "g", "ge", or "get" causes
|
||||
response degradation, set ["get"] to this option and avoid it.
|
||||
|
||||
*g:acp_behaviorFileLength* >
|
||||
let g:acp_behaviorFileLength = 0
|
||||
<
|
||||
Length of filename characters before the cursor, which are needed to
|
||||
attempt filename completion. If negative value, this completion will
|
||||
be never attempted.
|
||||
|
||||
*g:acp_behaviorRubyOmniMethodLength* >
|
||||
let g:acp_behaviorRubyOmniMethodLength = 0
|
||||
<
|
||||
Length of keyword characters before the cursor, which are needed to
|
||||
attempt ruby omni-completion for methods. If negative value, this
|
||||
completion will be never attempted.
|
||||
|
||||
*g:acp_behaviorRubyOmniSymbolLength* >
|
||||
let g:acp_behaviorRubyOmniSymbolLength = 1
|
||||
<
|
||||
Length of keyword characters before the cursor, which are needed to
|
||||
attempt ruby omni-completion for symbols. If negative value, this
|
||||
completion will be never attempted.
|
||||
|
||||
*g:acp_behaviorPythonOmniLength* >
|
||||
let g:acp_behaviorPythonOmniLength = 0
|
||||
<
|
||||
Length of keyword characters before the cursor, which are needed to
|
||||
attempt python omni-completion. If negative value, this completion
|
||||
will be never attempted.
|
||||
|
||||
*g:acp_behaviorPerlOmniLength* >
|
||||
let g:acp_behaviorPerlOmniLength = -1
|
||||
<
|
||||
Length of keyword characters before the cursor, which are needed to
|
||||
attempt perl omni-completion. If negative value, this completion will
|
||||
be never attempted.
|
||||
|
||||
See also: |acp-perl-omni|
|
||||
|
||||
*g:acp_behaviorXmlOmniLength* >
|
||||
let g:acp_behaviorXmlOmniLength = 0
|
||||
<
|
||||
Length of keyword characters before the cursor, which are needed to
|
||||
attempt XML omni-completion. If negative value, this completion will
|
||||
be never attempted.
|
||||
|
||||
*g:acp_behaviorHtmlOmniLength* >
|
||||
let g:acp_behaviorHtmlOmniLength = 0
|
||||
<
|
||||
Length of keyword characters before the cursor, which are needed to
|
||||
attempt HTML omni-completion. If negative value, this completion will
|
||||
be never attempted.
|
||||
|
||||
*g:acp_behaviorCssOmniPropertyLength* >
|
||||
let g:acp_behaviorCssOmniPropertyLength = 1
|
||||
<
|
||||
Length of keyword characters before the cursor, which are needed to
|
||||
attempt CSS omni-completion for properties. If negative value, this
|
||||
completion will be never attempted.
|
||||
|
||||
*g:acp_behaviorCssOmniValueLength* >
|
||||
let g:acp_behaviorCssOmniValueLength = 0
|
||||
<
|
||||
Length of keyword characters before the cursor, which are needed to
|
||||
attempt CSS omni-completion for values. If negative value, this
|
||||
completion will be never attempted.
|
||||
|
||||
*g:acp_behavior* >
|
||||
let g:acp_behavior = {}
|
||||
<
|
||||
This option is for advanced users. This setting overrides other
|
||||
behavior options. This is a |Dictionary|. Each key corresponds to a
|
||||
filetype. '*' is default. Each value is a list. These are attempted in
|
||||
sequence until completion item is found. Each element is a
|
||||
|Dictionary| which has following items:
|
||||
|
||||
"command": *g:acp_behavior-command*
|
||||
Command to be fed to open popup menu for completions.
|
||||
|
||||
"completefunc": *g:acp_behavior-completefunc*
|
||||
'completefunc' will be set to this user-provided function during the
|
||||
completion. Only makes sense when "command" is "<C-x><C-u>".
|
||||
|
||||
"meets": *g:acp_behavior-meets*
|
||||
Name of the function which dicides whether or not to attempt this
|
||||
completion. It will be attempted if this function returns non-zero.
|
||||
This function takes a text before the cursor.
|
||||
|
||||
"onPopupClose": *g:acp_behavior-onPopupClose*
|
||||
Name of the function which is called when popup menu for this
|
||||
completion is closed. Following completions will be suppressed if
|
||||
this function returns zero.
|
||||
|
||||
"repeat": *g:acp_behavior-repeat*
|
||||
If non-zero, the last completion is automatically repeated.
|
||||
|
||||
|
||||
==============================================================================
|
||||
SPECIAL THANKS *acp-thanks*
|
||||
|
||||
- Daniel Schierbeck
|
||||
- Ingo Karkat
|
||||
|
||||
|
||||
==============================================================================
|
||||
CHANGELOG *acp-changelog*
|
||||
|
||||
2.14.1
|
||||
- Changed the way of auto-popup for avoiding an issue about filename
|
||||
completion.
|
||||
- Fixed a bug that popup menu was opened twice when auto-popup was done.
|
||||
|
||||
2.14
|
||||
- Added the support for perl-completion.vim.
|
||||
|
||||
2.13
|
||||
- Changed to sort snipMate's triggers.
|
||||
- Fixed a bug that a wasted character was inserted after snipMate's trigger
|
||||
completion.
|
||||
|
||||
2.12.1
|
||||
- Changed to avoid a strange behavior with Microsoft IME.
|
||||
|
||||
2.12
|
||||
- Added g:acp_behaviorKeywordIgnores option.
|
||||
- Added g:acp_behaviorUserDefinedMeets option and removed
|
||||
g:acp_behaviorUserDefinedPattern.
|
||||
- Changed to do auto-popup only when a buffer is modified.
|
||||
- Changed the structure of g:acp_behavior option.
|
||||
- Changed to reflect a change of behavior options (named g:acp_behavior*)
|
||||
any time it is done.
|
||||
- Fixed a bug that completions after omni completions or snipMate's trigger
|
||||
completion were never attempted when no candidate for the former
|
||||
completions was found.
|
||||
|
||||
2.11.1
|
||||
- Fixed a bug that a snipMate's trigger could not be expanded when it was
|
||||
completed.
|
||||
|
||||
2.11
|
||||
- Implemented experimental feature which is snipMate's trigger completion.
|
||||
|
||||
2.10
|
||||
- Improved the response by changing not to attempt any completion when
|
||||
keyword characters are entered after a word which has been found that it
|
||||
has no completion candidate at the last attempt of completions.
|
||||
- Improved the response by changing to close popup menu when <BS> was
|
||||
pressed and the text before the cursor would not match with the pattern of
|
||||
current behavior.
|
||||
|
||||
2.9
|
||||
- Changed default behavior to support XML omni completion.
|
||||
- Changed default value of g:acp_behaviorKeywordCommand option.
|
||||
The option with "\<C-p>" cause a problem which inserts a match without
|
||||
<CR> when 'dictionary' has been set and keyword completion is done.
|
||||
- Changed to show error message when incompatible with a installed vim.
|
||||
|
||||
2.8.1
|
||||
- Fixed a bug which inserted a selected match to the next line when
|
||||
auto-wrapping (enabled with 'formatoptions') was performed.
|
||||
|
||||
2.8
|
||||
- Added g:acp_behaviorUserDefinedFunction option and
|
||||
g:acp_behaviorUserDefinedPattern option for users who want to make custom
|
||||
completion auto-popup.
|
||||
- Fixed a bug that setting 'spell' on a new buffer made typing go crazy.
|
||||
|
||||
2.7
|
||||
- Changed naming conventions for filenames, functions, commands, and options
|
||||
and thus renamed them.
|
||||
- Added g:acp_behaviorKeywordCommand option. If you prefer the previous
|
||||
behavior for keyword completion, set this option "\<C-n>".
|
||||
- Changed default value of g:acp_ignorecaseOption option.
|
||||
|
||||
The following were done by Ingo Karkat:
|
||||
|
||||
- ENH: Added support for setting a user-provided 'completefunc' during the
|
||||
completion, configurable via g:acp_behavior.
|
||||
- BUG: When the configured completion is <C-p> or <C-x><C-p>, the command to
|
||||
restore the original text (in on_popup_post()) must be reverted, too.
|
||||
- BUG: When using a custom completion function (<C-x><C-u>) that also uses
|
||||
an s:...() function name, the s:GetSidPrefix() function dynamically
|
||||
determines the wrong SID. Now calling s:DetermineSidPrefix() once during
|
||||
sourcing and caching the value in s:SID.
|
||||
- BUG: Should not use custom defined <C-X><C-...> completion mappings. Now
|
||||
consistently using unmapped completion commands everywhere. (Beforehand,
|
||||
s:PopupFeeder.feed() used mappings via feedkeys(..., 'm'), but
|
||||
s:PopupFeeder.on_popup_post() did not due to its invocation via
|
||||
:map-expr.)
|
||||
|
||||
2.6:
|
||||
- Improved the behavior of omni completion for HTML/XHTML.
|
||||
|
||||
2.5:
|
||||
- Added some options to customize behavior easily:
|
||||
g:AutoComplPop_BehaviorKeywordLength
|
||||
g:AutoComplPop_BehaviorFileLength
|
||||
g:AutoComplPop_BehaviorRubyOmniMethodLength
|
||||
g:AutoComplPop_BehaviorRubyOmniSymbolLength
|
||||
g:AutoComplPop_BehaviorPythonOmniLength
|
||||
g:AutoComplPop_BehaviorHtmlOmniLength
|
||||
g:AutoComplPop_BehaviorCssOmniPropertyLength
|
||||
g:AutoComplPop_BehaviorCssOmniValueLength
|
||||
|
||||
2.4:
|
||||
- Added g:AutoComplPop_MappingDriven option.
|
||||
|
||||
2.3.1:
|
||||
- Changed to set 'lazyredraw' while a popup menu is visible to avoid
|
||||
flickering.
|
||||
- Changed a behavior for CSS.
|
||||
- Added support for GetLatestVimScripts.
|
||||
|
||||
2.3:
|
||||
- Added a behavior for Python to support omni completion.
|
||||
- Added a behavior for CSS to support omni completion.
|
||||
|
||||
2.2:
|
||||
- Changed not to work when 'paste' option is set.
|
||||
- Fixed AutoComplPopEnable command and AutoComplPopDisable command to
|
||||
map/unmap "i" and "R".
|
||||
|
||||
2.1:
|
||||
- Fixed the problem caused by "." command in Normal mode.
|
||||
- Changed to map "i" and "R" to feed completion command after starting
|
||||
Insert mode.
|
||||
- Avoided the problem caused by Windows IME.
|
||||
|
||||
2.0:
|
||||
- Changed to use CursorMovedI event to feed a completion command instead of
|
||||
key mapping. Now the auto-popup is triggered by moving the cursor.
|
||||
- Changed to feed completion command after starting Insert mode.
|
||||
- Removed g:AutoComplPop_MapList option.
|
||||
|
||||
1.7:
|
||||
- Added behaviors for HTML/XHTML. Now supports the omni completion for
|
||||
HTML/XHTML.
|
||||
- Changed not to show expressions for CTRL-R =.
|
||||
- Changed not to set 'nolazyredraw' while a popup menu is visible.
|
||||
|
||||
1.6.1:
|
||||
- Changed not to trigger the filename completion by a text which has
|
||||
multi-byte characters.
|
||||
|
||||
1.6:
|
||||
- Redesigned g:AutoComplPop_Behavior option.
|
||||
- Changed default value of g:AutoComplPop_CompleteOption option.
|
||||
- Changed default value of g:AutoComplPop_MapList option.
|
||||
|
||||
1.5:
|
||||
- Implemented continuous-completion for the filename completion. And added
|
||||
new option to g:AutoComplPop_Behavior.
|
||||
|
||||
1.4:
|
||||
- Fixed the bug that the auto-popup was not suspended in fuzzyfinder.
|
||||
- Fixed the bug that an error has occurred with Ruby-omni-completion unless
|
||||
Ruby interface.
|
||||
|
||||
1.3:
|
||||
- Supported Ruby-omni-completion by default.
|
||||
- Supported filename completion by default.
|
||||
- Added g:AutoComplPop_Behavior option.
|
||||
- Added g:AutoComplPop_CompleteoptPreview option.
|
||||
- Removed g:AutoComplPop_MinLength option.
|
||||
- Removed g:AutoComplPop_MaxLength option.
|
||||
- Removed g:AutoComplPop_PopupCmd option.
|
||||
|
||||
1.2:
|
||||
- Fixed bugs related to 'completeopt'.
|
||||
|
||||
1.1:
|
||||
- Added g:AutoComplPop_IgnoreCaseOption option.
|
||||
- Added g:AutoComplPop_NotEnableAtStartup option.
|
||||
- Removed g:AutoComplPop_LoadAndEnable option.
|
||||
1.0:
|
||||
- g:AutoComplPop_LoadAndEnable option for a startup activation is added.
|
||||
- AutoComplPopLock command and AutoComplPopUnlock command are added to
|
||||
suspend and resume.
|
||||
- 'completeopt' and 'complete' options are changed temporarily while
|
||||
completing by this script.
|
||||
|
||||
0.4:
|
||||
- The first match are selected when the popup menu is Opened. You can insert
|
||||
the first match with CTRL-Y.
|
||||
|
||||
0.3:
|
||||
- Fixed the problem that the original text is not restored if 'longest' is
|
||||
not set in 'completeopt'. Now the plugin works whether or not 'longest' is
|
||||
set in 'completeopt', and also 'menuone'.
|
||||
|
||||
0.2:
|
||||
- When completion matches are not found, insert CTRL-E to stop completion.
|
||||
- Clear the echo area.
|
||||
- Fixed the problem in case of dividing words by symbols, popup menu is
|
||||
not opened.
|
||||
|
||||
0.1:
|
||||
- First release.
|
||||
|
||||
|
||||
==============================================================================
|
||||
ABOUT *acp-about* *acp-contact* *acp-author*
|
||||
|
||||
Author: Takeshi NISHIDA <ns9tks@DELETE-ME.gmail.com>
|
||||
Licence: MIT Licence
|
||||
URL: http://www.vim.org/scripts/script.php?script_id=1879
|
||||
http://bitbucket.org/ns9tks/vim-autocomplpop/
|
||||
|
||||
Bugs/Issues/Suggestions/Improvements ~
|
||||
|
||||
Please submit to http://bitbucket.org/ns9tks/vim-autocomplpop/issues/ .
|
||||
|
||||
==============================================================================
|
||||
vim:tw=78:ts=8:ft=help:norl:
|
||||
|
||||
710
doc/project.txt
710
doc/project.txt
@@ -1,710 +0,0 @@
|
||||
*project.txt* Plugin for managing multiple projects with multiple sources
|
||||
For Vim version 6.x and Vim version 7.x.
|
||||
Last Change: Fri 13 Oct 2006 10:20:13 AM EDT
|
||||
|
||||
|
||||
By Aric Blumer
|
||||
aricvim email-at-sign charter.net
|
||||
|
||||
*project* *project-plugin*
|
||||
Contents:
|
||||
|
||||
Commands...................|project-invoking|
|
||||
Inheritance.............|project-inheritance|
|
||||
Mappings...................|project-mappings|
|
||||
Adding Mappings.....|project-adding-mappings|
|
||||
Settings...................|project-settings|
|
||||
Example File................|project-example|
|
||||
Tips...........................|project-tips|
|
||||
|
||||
|
||||
You can use this plugin's basic functionality to set up a list of
|
||||
frequently-accessed files for easy navigation. The list of files will be
|
||||
displayed in a window on the left side of the Vim window, and you can press
|
||||
<Return> or double-click on filenames in the list to open the files. I find
|
||||
this easier to use than having to navigate a directory hierarchy with the
|
||||
|file-explorer|.
|
||||
|
||||
You can also instruct the Plugin to change to a directory and to run Vim
|
||||
scripts when you select a file. These scripts can, for example, modify the
|
||||
environment to include compilers in $PATH. This makes it very easy to use
|
||||
quickfix with multiple projects that use different environments.
|
||||
|
||||
Other features include:
|
||||
o Loading/Unloading all the files in a Project (\l, \L, \w, and \W)
|
||||
o Grepping all the files in a Project (\g and \G)
|
||||
o Running a user-specified script on a file (can be used to launch an
|
||||
external program on the file) (\1 through \9)
|
||||
o Running a user-specified script on all the files in a Project
|
||||
(\f1-\f9 and \F1-\F9)
|
||||
o High degree of user-configurability
|
||||
o Also works with |netrw| using the XXXX://... notation where XXXX is
|
||||
ftp, rcp, scp, or http.
|
||||
|
||||
All of this is specified within a simple text file and a few global variables
|
||||
in your vimrc file.
|
||||
|
||||
You must set 'nocompatible' in your |vimrc| file to use this plugin. You can
|
||||
stop the plugin from being loaded by setting the "loaded_project" variable: >
|
||||
:let loaded_project = 1
|
||||
|
||||
|
||||
==============================================================================
|
||||
COMMANDS *project-invoking*
|
||||
|
||||
You can use the plugin by placing it in your plugin directory (e.g.,
|
||||
~/.vim/plugin). See |add-global-plugin|. When you start vim the next time, you
|
||||
then enter the command >
|
||||
:Project
|
||||
or >
|
||||
:Project {file}
|
||||
|
||||
If you do not specify the filename, $HOME/.vimprojects is used.
|
||||
|
||||
To have Vim come up with the Project Window enabled automatically (say, from a
|
||||
GUI launcher), run Vim like this: [g]vim +Project
|
||||
|
||||
Note that you can invoke :Project on only one file at a time. If you wish to
|
||||
change the Project File, do a :bwipe in the Project Buffer, then re-invoke the
|
||||
Plugin as described above.
|
||||
|
||||
Several Projects can be kept and displayed in the same file, each in a fold
|
||||
delimited by { and } (see |fold.txt|). There can be any number of nested
|
||||
folds to provide you with a Project hierarchy. Any line without a { or a } in
|
||||
the file is considered to be a filename. Blank lines are ignored, and any
|
||||
text after a # is ignored.
|
||||
|
||||
Because the plugin uses standard Vim folds, you can use any of the
|
||||
|fold-commands|. You can double-click on the first line of a fold to open and
|
||||
close it. You can select a file to open by putting the cursor on its name and
|
||||
pressing <Return> or by double-clicking on it. The plugin will create a new
|
||||
window to the right or use the |CTRL-W_p| equivalent if it exists.
|
||||
|
||||
*project-syntax*
|
||||
Each Project Entry has this form:
|
||||
|
||||
project_entry ::=
|
||||
<Description>={projpath} [{options}] {
|
||||
[ filename ]
|
||||
[ project_entry ]
|
||||
}
|
||||
|
||||
{options} is one or more of the following (on the same line):
|
||||
CD={path}
|
||||
in={filename}
|
||||
out={filename}
|
||||
filter="{pat}"
|
||||
flags={flag}
|
||||
|
||||
Note that a project_entry can reside within a project_entry. This allows you
|
||||
to set up a hierarchy within your Project.
|
||||
|
||||
The <Description> will be displayed in the foldtext and cannot contain "=".
|
||||
There can be no space character directly on either side of the =.
|
||||
|
||||
The {projpath} is the path in which the files listed in the Project's fold
|
||||
will be found, and it may contain environment variables. If the path is a
|
||||
relative path, then the plugin constructs the whole path from the Project's
|
||||
parent, grandparent, etc., all the way up the hierarchy. An outermost
|
||||
project_entry must have an absolute path. See the |project-inheritance|
|
||||
example below. {projpath} may contain spaces, but they must be escaped like
|
||||
normal Vim escapes. Here are two examples of the same directory:
|
||||
>
|
||||
Example=/my/directory/with\ spaces {
|
||||
}
|
||||
Example="/my/directory/with spaces" {
|
||||
}
|
||||
|
||||
I recommend this for Windows<77>: >
|
||||
|
||||
Example="c:\My Documents" {
|
||||
}
|
||||
|
||||
But Vim is smart enough to do this, too: >
|
||||
|
||||
Example=c:\My\ Documents {
|
||||
}
|
||||
|
||||
CD= provides the directory that Vim will change to when you select a file in
|
||||
that fold (using |:cd|). This allows you, for example, to enter |:make| to use
|
||||
the local Makefile. A CD=. means that Vim will make {projpath} or its
|
||||
inherited equivalent the current working directory. When CD is omitted, the
|
||||
directory is not changed. There can be no space on either side of the =. The
|
||||
value of CD can also be a relative path from a parent's CD. See the
|
||||
|project-inheritance| example below. This directive is ignored for |netrw|
|
||||
projects. Spaces are allowed in the path as for {projpath}.
|
||||
|
||||
in= and out= provide the means to run arbitrary Vim scripts whenever you enter
|
||||
or leave a file's buffer (see the |BufEnter| and |BufLeave| autocommand
|
||||
events). The idea is to have a Vim script that sets up or tears down the
|
||||
environment for the Project like this:
|
||||
|
||||
in.vim: >
|
||||
let $PROJECT_HOME='~/my_project'
|
||||
" Put the compiler in $PATH
|
||||
if $PATH !~ '/path/to/my/compiler'
|
||||
let $PATH=$PATH.':/path/to/my/compiler'
|
||||
endif
|
||||
|
||||
out.vim: >
|
||||
" Remove compiler from $PATH
|
||||
if $PATH =~ '/path/to/my/compiler'
|
||||
let $PATH=substitute($PATH, ':/path/to/my/compiler', '', 'g')
|
||||
endif
|
||||
|
||||
Then you can use :make with the proper environment depending on what file you
|
||||
are currently editing. If the path to the script is relative, then it is
|
||||
relative from {projpath}. These directives are inherited by Subprojects
|
||||
unless the Subproject specifies its own. For use with |netrw| projects, the
|
||||
paths specified for in= and out= must be absolute and local.
|
||||
|
||||
filter= specifies a |glob()| file pattern. It is used to regenerate the list
|
||||
of files in a Project fold when using the \r (<LocalLeader>r) map in the
|
||||
Project Window. The filter value must be in quotes because it can contain
|
||||
multiple file patterns. If filter is omitted, then the * pattern is used.
|
||||
There can be no space on either side of the =. A Subproject will inherit the
|
||||
filter of its parent unless it specifies its own filter.
|
||||
|
||||
flags= provides the means to enable/disable features for a particular fold.
|
||||
The general mnemonic scheme is for lower case to turn something off and upper
|
||||
case to turn something on. {flag} can contain any of the following
|
||||
characters:
|
||||
|
||||
flag Description ~
|
||||
|
||||
l Turn off recursion for this fold for \L. Subfolds are also
|
||||
blocked from the recursion.
|
||||
|
||||
r Turn off refresh. When present, do not refresh this fold when
|
||||
\r or \R is used. This does not affect subfold recursion.
|
||||
|
||||
S Turn on sorting for refresh and create.
|
||||
|
||||
s Turn off sorting for refresh and create.
|
||||
|
||||
T Turn on top gravity. Forces folds to the top of the current
|
||||
fold when refreshing. It has the same affect as the 'T' flag
|
||||
in g:proj_flags, but controls the feature on a per-fold basis.
|
||||
|
||||
t Turn off top gravity. Forces folds to the bottom of the
|
||||
current fold when refreshing.
|
||||
|
||||
w Turn off recursion for this fold for \W. Subfolds are also
|
||||
blocked from the recursion.
|
||||
|
||||
|
||||
Flags are not inherited by Subprojects.
|
||||
|
||||
Any text outside a fold is ignored.
|
||||
|
||||
|
||||
==============================================================================
|
||||
INHERITANCE *project-inheritance*
|
||||
|
||||
It's best to show inheritance by comparing these two Project Files:
|
||||
>
|
||||
Parent=~/my_project CD=. filter="Make* *.mk" flags=r {
|
||||
Child1=c_code {
|
||||
}
|
||||
Child2=include CD=. filter="*.h" {
|
||||
}
|
||||
}
|
||||
|
||||
Child1's path is "~/my_project/c_code" because ~/my_project is inherited. It
|
||||
also inherits the CD from Parent. Since Parent has CD=., the Parent's cwd is
|
||||
"~/my_project". Child1 therefore inherits a CD of "~/my_project". Finally,
|
||||
Child1 inherits the filter from Parent. The flags are not inherited.
|
||||
|
||||
Child2 only inherits the "~/my_project" from Parent.
|
||||
|
||||
Thus, the example above is exactly equivalent to this:
|
||||
>
|
||||
Parent=~/my_project CD=. filter="Make* *.mk" flags=r {
|
||||
Child1=~/my_project/c_code CD=~/my_project filter="Make* *.mk" {
|
||||
}
|
||||
Child2=~/my_project/include CD=~/my_project/include filter="*.h" {
|
||||
}
|
||||
}
|
||||
|
||||
(For a real Project, Child1 would not want to inherit its parent's filter, but
|
||||
this example shows the concept.) You can always enter \i to display what the
|
||||
cursor's project inherits.
|
||||
|
||||
|
||||
==============================================================================
|
||||
MAPPINGS *project-mappings*
|
||||
|
||||
Map Action ~
|
||||
|
||||
\r Refreshes the Project fold that the cursor is in by placing in the
|
||||
fold all the files that match the filter. The Project is refreshed
|
||||
using an indent of one space for every foldlevel in the hierarchy.
|
||||
|
||||
You may place a "# pragma keep" (without the quotes) at the end of a
|
||||
line, and the file entry on that line will not be removed when you
|
||||
refresh. This is useful, for example, when you have . as an entry so
|
||||
you can easily browse the directory.
|
||||
|
||||
Note that this mapping is actually <LocalLeader>r, and the default of
|
||||
|<LocalLeader>| is \.
|
||||
|
||||
This does not work for Projects using |netrw|.
|
||||
|
||||
\R Executes \r recursively in the current fold and all folds below.
|
||||
This does not work for Projects using |netrw|.
|
||||
|
||||
\c Creates a Project fold entry. It asks for the description, the path
|
||||
to the files, the CD parameter, and the filename |glob()| pattern.
|
||||
From this information, it will create the Project Entry below the
|
||||
cursor.
|
||||
|
||||
This does not work for Projects using |netrw|.
|
||||
|
||||
\C Creates a Project fold entry like \c, but recursively includes all the
|
||||
subdirectories.
|
||||
|
||||
<Return>
|
||||
Select a file to open in the |CTRL-W_p| window or in a new window. If
|
||||
the cursor is on a fold, open or close it.
|
||||
|
||||
<S-Return>
|
||||
\s
|
||||
Same as <Return> but horizontally split the target window.
|
||||
<LocalLeader>s is provided for those terminals that don't recognize
|
||||
<S-Return>.
|
||||
|
||||
\S
|
||||
Load all files in a project by doing horizontal splits.
|
||||
|
||||
<C-Return>
|
||||
\o
|
||||
Same as <Return> but ensure that the opened file is the only other
|
||||
window. <LocalLeader>o is provided for those terminals that don't
|
||||
recognize <C-Return>.
|
||||
|
||||
<M-Return>
|
||||
\v
|
||||
Same as <Return> but only display the file--the cursor stays in the
|
||||
Project Window.
|
||||
|
||||
<2-LeftMouse>
|
||||
(Double-click) If on a closed fold, open it. If on an open fold
|
||||
boundary, close it. If on a filename, open the file in the |CTRL-W_p|
|
||||
window or in a new window.
|
||||
|
||||
<S-2-LeftMouse>
|
||||
Same as <S-Return>.
|
||||
|
||||
<C-2-LeftMouse>
|
||||
Same as <C-Return>.
|
||||
|
||||
<RightMouse>
|
||||
Increase the width of the Project Window by g:proj_window_increment or
|
||||
toggle between a width of
|
||||
g:proj_window_width + g:proj_window_increment
|
||||
and
|
||||
g:proj_window_width.
|
||||
|
||||
Whether you toggle or monotonically increase the width is determined
|
||||
by the 't' flag of the g:proj_flags variable (see |project-flags|).
|
||||
|
||||
Note that a Right Mouse click will not automatically place the cursor
|
||||
in the Project Window if it is in a different window. The window will
|
||||
go back to the g:proj_window_width width when you leave the window.
|
||||
|
||||
<space> Same as <RightMouse>
|
||||
|
||||
<CTRL-Up>
|
||||
\<Up>
|
||||
Move the text or fold under the cursor up one row. This may not work
|
||||
in a terminal because the terminal is unaware of this key combination.
|
||||
<LocalLeader><Up> is provided for those terminals that don't recognize
|
||||
<C-Up>.
|
||||
|
||||
|
||||
<CTRL-Down>
|
||||
\<Down>
|
||||
Move the text or fold under the cursor down one row. This may not work
|
||||
in a terminal because the terminal is unaware of this key combination.
|
||||
<LocalLeader><Down> is provided for those terminals that don't
|
||||
recognize <C-Down>.
|
||||
|
||||
\i Show in the status line the completely resolved and inherited
|
||||
parameters for the fold the cursor is in. This is intended for
|
||||
debugging your relative path and inherited parameters for manually
|
||||
entered Projects.
|
||||
|
||||
\I Show in the status line the completely resolved filename. Uses the
|
||||
Project_GetFname(line('.')) function.
|
||||
|
||||
\1 - \9
|
||||
Run the command specified in g:proj_run{x} where {x} is the number
|
||||
of the key. See the documentation of g:proj_run1 below.
|
||||
|
||||
\f1-\f9
|
||||
Run the command specified in g:proj_run_fold{x} where {x} is the
|
||||
number of the key. The command is run on the files at the current
|
||||
Project level. See the |project-settings| below.
|
||||
|
||||
\F1-\F9
|
||||
Run the command specified in g:proj_run_fold{x} where {x} is the
|
||||
number of the key. The command is run on the files at the current
|
||||
Project level and all Subprojects. See the |project-settings| below.
|
||||
|
||||
\0 Display the commands that are defined for \1 through \9.
|
||||
|
||||
\f0 Display the commands that are defined for \f1 through \f9 and \F1
|
||||
through \F0. Same as \F0.
|
||||
|
||||
\l Load all the files in the current Project level into Vim. While files
|
||||
are being loaded, you may press any key to stop.
|
||||
|
||||
\L Load all the files in the current Project and all Subprojects into
|
||||
Vim. Use this mapping with caution--I wouldn't suggest using \L to
|
||||
load a Project with thousands of files. (BTW, my Project file has more
|
||||
than 5,300 files in it!) While files are being loaded, you may press
|
||||
any key to stop.
|
||||
|
||||
\w Wipe all the files in the current Project level from Vim. (If files
|
||||
are modified, they will be saved first.) While files are being wiped,
|
||||
you may press any key to stop.
|
||||
|
||||
\W Wipe all the files in the current Project and all Subprojects from
|
||||
Vim. (If files are modified, they will be saved first.) While files
|
||||
are being wiped, you may press any key to stop.
|
||||
|
||||
\g Grep all the files in the current Project level.
|
||||
|
||||
\G Grep all the files in the current Project level and all Subprojects.
|
||||
|
||||
\e Set up the Environment for the Project File as though you had selected
|
||||
it with <Return>. This allows you to do a \e and a :make without
|
||||
having to open any files in the project.
|
||||
|
||||
\E Explore (using |file-explorer|) the directory of the project the
|
||||
cursor is in. Does not work with netrw.
|
||||
|
||||
<F12> When the 'g' flag is present in g:proj_flags (see |project-flags|)
|
||||
this key toggles the Project Window open and closed. You may remap
|
||||
this toggle function by putting the following in your vimrc and
|
||||
replacing <Leader>P with whatever key combination you wish:
|
||||
|
||||
nmap <silent> <Leader>P <Plug>ToggleProject
|
||||
|
||||
Note that the Project Plugin remaps :help because the Help Window and the
|
||||
Project Window get into a fight over placement. The mapping avoids the
|
||||
problem.
|
||||
|
||||
==============================================================================
|
||||
ADDING MAPPINGS *project-adding-mappings*
|
||||
|
||||
You can add your own mappings or change the mappings of the plugin by placing
|
||||
them in the file $HOME/.vimproject_mappings. This file, if it exists, will be
|
||||
sourced when the plugin in loaded. Here is an example that will count the
|
||||
number of entries in a project when you press \K (Kount, C is taken :-): >
|
||||
|
||||
function! s:Wc()
|
||||
let b:loadcount=0
|
||||
function! SpawnExec(infoline, fname, lineno, data)
|
||||
let b:loadcount = b:loadcount + 1
|
||||
if getchar(0) != 0 | let b:stop_everything=1 | endif
|
||||
endfunction
|
||||
call Project_ForEach(1, line('.'), "*SpawnExec", 0, '')
|
||||
delfunction SpawnExec
|
||||
echon b:loadcount." Files\r"
|
||||
unlet b:loadcount
|
||||
if exists("b:stop_everything")
|
||||
unlet b:stop_everything
|
||||
echon "Aborted.\r"
|
||||
endif
|
||||
endfunction
|
||||
|
||||
nnoremap <buffer> <silent> <LocalLeader>K :call <SID>Wc()<CR>
|
||||
|
||||
Here's another example of how I integrated the use of perforce with the plugin
|
||||
in my $HOME/.vimproject_mappings:
|
||||
>
|
||||
function! s:DoP4(cmd)
|
||||
let name=Project_GetFname(line('.'))
|
||||
let dir=substitute(name, '\(.*\)/.*', '\1', 'g')
|
||||
exec 'cd '.dir
|
||||
exec "!".a:cmd.' '.Project_GetFname(line('.'))
|
||||
cd -
|
||||
endfunction
|
||||
|
||||
nmap <buffer> <silent> \pa :call <SID>DoP4("p4add")<CR>
|
||||
nmap <buffer> <silent> \pe :call <SID>DoP4("p4edit")<CR>
|
||||
<
|
||||
(Note that I CD to the directory the file is in so I can pick of the $P4CONFIG
|
||||
file. See the perforce documentation.)
|
||||
|
||||
This creates the mappings \pe to check out the file for edit and \pa to add
|
||||
the file to the depot.
|
||||
|
||||
Here is another example where I remap the <Return> mapping to use an external
|
||||
program to launch a special kind of file (in this case, it launches ee to view
|
||||
a jpg file). It is a bit contrived, but it works.
|
||||
>
|
||||
let s:sid = substitute(maparg('<Return>', 'n'), '.*\(<SNR>.\{-}\)_.*', '\1', '')
|
||||
function! s:LaunchOrWhat()
|
||||
let fname=Project_GetFname(line('.'))
|
||||
if fname =~ '\.jpg$'
|
||||
exec 'silent! !ee "'.fname.'"&'
|
||||
else
|
||||
call {s:sid}_DoFoldOrOpenEntry('', 'e')
|
||||
endif
|
||||
endfunction
|
||||
nnoremap <buffer> <silent> <Return> \|:call <SID>LaunchOrWhat()<CR>
|
||||
<
|
||||
If the file ends in .jpg, the external program is launched, otherwise the
|
||||
original mapping of <Return> is run.
|
||||
|
||||
==============================================================================
|
||||
SETTINGS *project-settings*
|
||||
|
||||
You can set these variables in your vimrc file before the plugin is loaded to
|
||||
change its default behavior
|
||||
|
||||
g:proj_window_width
|
||||
The width of the Project Window that the plugin attempts to maintain.
|
||||
Default: 24
|
||||
|
||||
The Project Plugin is not always successful in keeping the window
|
||||
where I want it with the size specified here, but it does a decent
|
||||
job.
|
||||
|
||||
g:proj_window_increment
|
||||
The increment by which to increase the width of the Project Window
|
||||
when pressing <space> or clicking the <LeftMouse>. Default: 100
|
||||
(See |project-mappings|.)
|
||||
|
||||
*project-flags*
|
||||
g:proj_flags
|
||||
Default: "imst"
|
||||
Various flags to control the behavior of the Project Plugin. This
|
||||
variable can contain any of the following character flags.
|
||||
|
||||
flag Description ~
|
||||
|
||||
b When present, use the |browse()| when selecting directories
|
||||
for \c and \C. This is off by default for Windows, because
|
||||
the windows browser does not allow you to select directories.
|
||||
|
||||
c When present, the Project Window will automatically close when
|
||||
you select a file.
|
||||
|
||||
F Float the Project Window. That is, turn off automatic
|
||||
resizing and placement. This allows placement between other
|
||||
windows that wish to share similar placement at the side of
|
||||
the screen. It is also particularly helpful for external
|
||||
window managers.
|
||||
|
||||
g When present, the mapping for <F12> will be created to toggle
|
||||
the Project Window open and closed.
|
||||
|
||||
i When present, display the filename and the current working
|
||||
directory in the command line when a file is selected for
|
||||
opening.
|
||||
|
||||
l When present, the Project Plugin will use the |:lcd| command
|
||||
rather than |:cd| to change directories when you select a file
|
||||
to open. This flag is really obsolete and not of much use
|
||||
because of L below.
|
||||
|
||||
L Similar to l, but install a BufEnter/Leave |:autocommand| to
|
||||
ensure that the current working directory is changed to the
|
||||
one specified in the fold CD specification whenever that
|
||||
buffer is active. (|:lcd| only changes the CWD for a window,
|
||||
not a buffer.)
|
||||
|
||||
m Turn on mapping of the |CTRL-W_o| and |CTRL-W_CTRL_O| normal
|
||||
mode commands to make the current buffer the only visible
|
||||
buffer, but keep the Project Window visible, too.
|
||||
|
||||
n When present, numbers will be turned on for the project
|
||||
window.
|
||||
|
||||
s When present, the Project Plugin will use syntax highlighting
|
||||
in the Project Window.
|
||||
|
||||
S Turn on sorting for refresh and create.
|
||||
|
||||
t When present, toggle the size of the window rather than just
|
||||
increase the size when pressing <space> or right-clicking.
|
||||
See the entry for <RightMouse> in |project-mappings|.
|
||||
|
||||
T When present, put Subproject folds at the top of the fold when
|
||||
refreshing.
|
||||
|
||||
v When present, use :vimgrep rather than :grep when using \G.
|
||||
|
||||
g:proj_run1 ... g:proj_run9
|
||||
Contains a Vim command to execute on the file. See the
|
||||
mappings of \1 to \9 above.
|
||||
|
||||
%f is replaced with the full path and filename
|
||||
%F is replaced with the full path and filename with spaces
|
||||
quoted
|
||||
%n is replaced with the filename alone
|
||||
%N is replaced with the filename alone with spaces quoted
|
||||
%h is replaced with the home directory
|
||||
%H is replaced with the home directory with spaces quoted
|
||||
%r is replaced with the directory relative to the CD path
|
||||
%R is replaced with the directory relative to the CD path
|
||||
with spaces quoted
|
||||
%d is replaced with the CD directory.
|
||||
%D is replaced with the CD directory.with spaces quoted
|
||||
%% is replaced with a single % that is not used in
|
||||
expansion.
|
||||
|
||||
(Deprecated: %s is also replaced with the full path and
|
||||
filename for backward compatibility.)
|
||||
|
||||
For example, gvim will be launched on the file under the
|
||||
cursor when you enter \3 if the following is in your vimrc
|
||||
file: >
|
||||
let g:proj_run3='silent !gvim %f'
|
||||
< Here are a few other examples: >
|
||||
let g:proj_run1='!p4 edit %f'
|
||||
let g:proj_run2='!p4 add %f'
|
||||
let g:proj_run4="echo 'Viewing %f'|sil !xterm -e less %f &"
|
||||
<
|
||||
On Windows systems you will want to put the %f, %h, and %d in
|
||||
single quotes to avoid \ escaping.
|
||||
|
||||
g:proj_run_fold1 ... g:proj_run_fold9
|
||||
Contains a Vim command to execute on the files in a fold. See
|
||||
the mappings of \f1 to \f9 and \F1 to \F9 above.
|
||||
|
||||
%f is the filename, %h is replaced with the project home
|
||||
directory, and %d is replaced with the CD directory. Multiple
|
||||
filenames can be handled in two ways:
|
||||
|
||||
The first (default) way is to have %f replaced with all the
|
||||
absolute filenames, and the command is run once. The second
|
||||
is to have the command run for each of the non-absolute
|
||||
filenames (%f is replaced with one filename at a time). To
|
||||
select the second behavior, put an '*' character at the
|
||||
beginning of the g:proj_run_fold{x} variable. (The '*' is
|
||||
stripped before the command is run.)
|
||||
|
||||
For example, note the difference between the following: >
|
||||
let g:proj_run_fold3="*echo '%h/%f'"
|
||||
let g:proj_run_fold4="echo '%f'"
|
||||
<
|
||||
Note that on Windows systems, you will want the %f, %h, and %c
|
||||
within single quotes, or the \ in the paths will cause
|
||||
problems. The alternative is to put them in |escape()|.
|
||||
|
||||
|
||||
==============================================================================
|
||||
PROJECT EXAMPLE FILE *project-example*
|
||||
|
||||
Here is an example ~/.vimprojects file: >
|
||||
|
||||
1 My Project=~/c/project CD=. in=in.vim out=out.vim flags=r {
|
||||
2 Makefile
|
||||
3 in.vim
|
||||
4 out.vim
|
||||
5 GUI Files=. filter="gui*.c gui*.h" {
|
||||
6 gui_window.c
|
||||
7 gui_dialog.c
|
||||
8 gui_list.c
|
||||
9 gui.h # Header file
|
||||
10 }
|
||||
11 Database Files=. filter="data*.c data*.h" {
|
||||
12 data_read.c
|
||||
13 data_write.c
|
||||
14 data.h
|
||||
15 }
|
||||
16 OS-Specific Files {
|
||||
17 Win32=. filter="os_win32*.c os_win32*.h" {
|
||||
18 os_win32_gui.c
|
||||
19 os_win32_io.c
|
||||
20 }
|
||||
21 Unix=. filter="os_unix*.c os_unix*.h" {
|
||||
22 os_unix_gui.c
|
||||
23 os_unix_io.c
|
||||
24 }
|
||||
25 }
|
||||
26 }
|
||||
|
||||
(Don't type in the line numbers, of course.)
|
||||
|
||||
|
||||
==============================================================================
|
||||
TIPS ON USING PROJECT PLUGIN *project-tips*
|
||||
|
||||
1. You can create a Project Entry by entering this: >
|
||||
|
||||
Label=~/wherever CD=. filter="*.c *.h" {
|
||||
}
|
||||
<
|
||||
Then you can put the cursor in the fold and press \r. The script will fill
|
||||
in the files (C files in this case) from this directory for you. This is
|
||||
equivalent to \c without any dialogs.
|
||||
|
||||
2. You can edit the Project File at any time to add, remove, or reorder files
|
||||
in the Project list.
|
||||
|
||||
3. If the Project Window ever gets closed, you can just enter >
|
||||
:Project
|
||||
< to bring it back again. (You don't need to give it the filename; the
|
||||
plugin remembers.)
|
||||
|
||||
If you have the 'm' flag set in g:proj_flags, then you get the Project
|
||||
Window to show up again by pressing |CTRL-W_o|. This, of course, will
|
||||
close any other windows that may be open that the cursor is not in.
|
||||
|
||||
4. Adding files to a Project is very easy. To add, for example, the 'more.c'
|
||||
file to the Project, just insert the filename in the Project Entry then
|
||||
hit <Return> on it.
|
||||
|
||||
5. When |quickfix| loads files, it is not equivalent to pressing <Return> on
|
||||
a filename, so the directory will not be changed and the scripts will not
|
||||
be run. (If I could make this otherwise, I would.) The solution is to use
|
||||
the \L key to load all of the files in the Project before running
|
||||
quickfix.
|
||||
|
||||
6. If the Project window gets a bit cluttered with folds partially
|
||||
open/closed, you can press |zM| to close everything and tidy it up.
|
||||
|
||||
7. For advanced users, I am exporting the function Project_GetAllFnames()
|
||||
which returns all the filenames within a fold and optionally all its
|
||||
Subprojects. Also, I export Project_ForEach() for running a function for
|
||||
each filename in the project. See the code for examples on how to use
|
||||
these. Finally, I export Project_GetFname(line_number) so that you can
|
||||
write your own mappings and get the filename for it.
|
||||
|
||||
8. Some people have asked how to do a global mapping to take the cursor to
|
||||
the Project window. One of my goals for the plugin is for it to be as
|
||||
self-contained as possible, so I'm not going to add it by default. But you
|
||||
can put this in your vimrc:
|
||||
>
|
||||
nmap <silent> <Leader>P :Project<CR>
|
||||
|
||||
<
|
||||
9. You can put the . entry in a project, and it will launch the
|
||||
|file-explorer| plugin on the directory. To avoid removal when you
|
||||
refresh, make the entry look like this:
|
||||
>
|
||||
. # pragma keep
|
||||
<
|
||||
==============================================================================
|
||||
THANKS
|
||||
|
||||
The following people have sent me patches to help with the Project
|
||||
Plugin development:
|
||||
|
||||
Tomas Zellerin
|
||||
Lawrence Kesteloot
|
||||
Dave Eggum
|
||||
A Harrison
|
||||
Thomas Link
|
||||
Richard Bair
|
||||
Eric Arnold
|
||||
Peter Jones
|
||||
Eric Van Dewoestine
|
||||
|
||||
|
||||
vim:ts=8 sw=8 noexpandtab tw=78 ft=help:
|
||||
198
doc/vimblogger_ft.txt
Normal file
198
doc/vimblogger_ft.txt
Normal file
@@ -0,0 +1,198 @@
|
||||
*vimblogger_ft.txt* reStructuredText to Blogger Interface
|
||||
Author: Roman Dobosz, gryf73 at gmail com
|
||||
|
||||
Simple interface to create blog articles in rsST format. It provides
|
||||
commands for preview in browser, post and delete articles.
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
Requirements~
|
||||
|
||||
Module for communication was written in Python. So, VIm has to be
|
||||
compiled with +python.
|
||||
|
||||
Other requirements:
|
||||
|
||||
- Python (tested with version 2.6, should work also in others)
|
||||
- gdata http://code.google.com/p/gdata-python-client
|
||||
- docutils http://docutils.sourceforge.net
|
||||
- pygments http://pygments.org
|
||||
- Blogger account
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
Install~
|
||||
|
||||
Extract zip file into your ~/.vim.
|
||||
|
||||
========================================================================
|
||||
Usage~
|
||||
|
||||
This plugin is targeting for people, who has blogger account, want to
|
||||
use vim for creating blog articles and don't really likes to manually do
|
||||
this in html.
|
||||
|
||||
Unfortunately it has several limitations, like you cannot use multiple
|
||||
blogs or edit existing articles without reST source files. You have to
|
||||
somehow convert it reStructuredText, add *Id* and then update it.
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
Options~
|
||||
*g:blogger_browser*
|
||||
g:blogger_browser (default: 0)
|
||||
|
||||
If set to 1 output file from :PreviewBlogArticle will be opened in
|
||||
browser (used webbrowser Python module)
|
||||
|
||||
*g:blogger_name*
|
||||
g:blogger_name (default: "")
|
||||
|
||||
This is blog name, which is part of the URL, and you was obligated
|
||||
to enter it during blog creation. If you don't remember it, just
|
||||
check first part od the URL of your blog, just after 'http://'.
|
||||
Don't be confused with the blog title.
|
||||
|
||||
*g:blogger_login*
|
||||
g:blogger_login (default: "")
|
||||
|
||||
Google login name, usually gmail address.
|
||||
*g:blogger_pass*
|
||||
g:blogger_pass (default: "")
|
||||
|
||||
Password. If set to empty string, You'll be asked for it every time
|
||||
you do any blogger activity.
|
||||
*g:blogger_draft*
|
||||
g:blogger_draft (default: 1)
|
||||
|
||||
By default, don't publish articles immediately, just save it on the
|
||||
service. If set to 0, article will be published.
|
||||
|
||||
*g:blogger_maxarticles*
|
||||
g:blogger_maxarticles (default: 0)
|
||||
|
||||
Number of displayed articles during deletion. 0 means all. Any
|
||||
positive number will display only that numbers of articles on list.
|
||||
|
||||
*g:blogger_confirm_del*
|
||||
g:blogger_confirm_del (default: 1)
|
||||
|
||||
Confirm every deletion. If set to 0, suppress the confirmation.
|
||||
|
||||
*g:blogger_stylesheets*
|
||||
g:blogger_stylesheets (default: [])
|
||||
|
||||
List of relative paths (relative to generated HTML document) of CSS
|
||||
stylesheets, used only for article preview in HTML document. Usually
|
||||
one wanted to save stylesheets from his own blog, so that article
|
||||
can be displayed almost in the same way as in blog.
|
||||
|
||||
========================================================================
|
||||
Commands~
|
||||
|
||||
*:PreviewBlogArticle*
|
||||
|
||||
Generate article in HTML format, save it to the file with te same
|
||||
name as a reST source with .html extension in the same directory,
|
||||
and optionally opens it in browser. No connection to the blogger is
|
||||
performed.
|
||||
|
||||
*:SendBlogArticle*
|
||||
|
||||
Generate partial HTML document, which holds article, from current
|
||||
reST buffer and send it to the blog.
|
||||
|
||||
See reST document structure below for further description.
|
||||
|
||||
*:DeleteBlogArticle*
|
||||
|
||||
Display list of articles, and lets user choose one (or none) of them
|
||||
to perform deletions.
|
||||
|
||||
========================================================================
|
||||
reST document structure~
|
||||
|
||||
It is assumed, that following template will be used:
|
||||
|
||||
-----8<-----
|
||||
:Id:
|
||||
:Title: Title for the blog
|
||||
:Date:
|
||||
:Modified:
|
||||
:Tags: some, tags
|
||||
|
||||
Penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nulla
|
||||
facilisis massa ut massa. Sed nisi purus, malesuada eu, porta vulputate,
|
||||
suscipit auctor, nunc. Vestibulum convallis, augue eu luctus malesuada,
|
||||
mi ante mattis odio, ac venenatis neque sem vitae nisi.
|
||||
|
||||
.. more
|
||||
|
||||
|
||||
heading
|
||||
-------
|
||||
|
||||
**Congue** mi, quis posuere augue nulla a augue. Pellentesque sed est.
|
||||
Mauris cursus urna id lectus. Integer dignissim feugiat eros. Sed tempor
|
||||
volutpat dolor. Vestibulum vel lectus nec mauris semper adipiscing.
|
||||
|
||||
Aliquam tincidunt enim sit amet tellus. Sed mauris nulla, semper
|
||||
tincidunt, luctus a, sodales eget, leo. Sed ligula augue, cursus et.
|
||||
----->8-----
|
||||
|
||||
reST document (optionally) starts with *docinfo* section (first several
|
||||
lines, that are starting from *:* character) separaded from other
|
||||
content with one empty line.
|
||||
|
||||
Docinfo items holds article attributes, and are updated automatically
|
||||
every each of upload to blogger, which is triggered by
|
||||
*:SendBlogArticle* command.
|
||||
|
||||
*:Id:*
|
||||
Holds article id on blogger side. If not defined, new article will
|
||||
be created (even if there is already existing one with the very same
|
||||
content). If wrong id is entered (or an Id of deleted article),
|
||||
exception will be raised, and no action on blogger side will be
|
||||
performed.
|
||||
|
||||
*:Title:*
|
||||
Holds article title. Can be changed when *:Id:* is obtained.
|
||||
|
||||
*:Date:*
|
||||
This is published date in RFC 3339
|
||||
http://www.ietf.org/rfc/rfc3339.txt format. If empty on first
|
||||
upload, it will be set to current date. Can be set/changed to
|
||||
desired date.
|
||||
|
||||
*:Modified:*
|
||||
This is read-only item, which store modification date which happens
|
||||
on blogger side.
|
||||
|
||||
*:Tags:*
|
||||
Comma separated list of tags (Labels). Can be empty.
|
||||
|
||||
All other items are ignored.
|
||||
|
||||
After docinfo block, article body should be placed using markup for
|
||||
reStructuredText.
|
||||
|
||||
Additionally, there is sourcecode directive, simple syntax highlighter
|
||||
using Pygments module. Very simple usage could be as follows:
|
||||
|
||||
-----8<-----
|
||||
.. sourcecode:: python
|
||||
|
||||
import vim
|
||||
print vim.current.buffer.name
|
||||
|
||||
----->8-----
|
||||
|
||||
Note: All headings for generated HTML by *:SendBlogArticle* will be
|
||||
shifted by 3, so the first heading will become <h3>, second <h4> and so
|
||||
on, to fit into blogger template (well, most of them). Remember, that
|
||||
HTML allow up to 6 level of headings, while reST doesn't have this
|
||||
limitation.
|
||||
|
||||
========================================================================
|
||||
Changelog~
|
||||
|
||||
0.1 First release
|
||||
|
||||
vim:tw=72:fo=tcq2:isk=!-~,^*,^|,^":ts=8:ft=help:norl:
|
||||
@@ -1,98 +0,0 @@
|
||||
" Blogger vim interface.
|
||||
" Provide some convinient functions for creating preview from the reST file
|
||||
" and to send articles to blog.
|
||||
|
||||
if exists("b:did_rst_plugin")
|
||||
finish " load only once
|
||||
else
|
||||
let b:did_rst_plugin = 1
|
||||
endif
|
||||
|
||||
if !exists("g:blogger_browser")
|
||||
let g:blogger_browser = 0
|
||||
endif
|
||||
|
||||
if !exists("g:blogger_name")
|
||||
let g:blogger_name = ""
|
||||
endif
|
||||
|
||||
if !exists("g:blogger_login")
|
||||
let g:blogger_login= ""
|
||||
endif
|
||||
|
||||
if !exists("g:blogger_pass")
|
||||
let g:blogger_pass = ""
|
||||
endif
|
||||
|
||||
map <F6> :call <SID>Restify()<cr>
|
||||
map <F7> :call <SID>Rst2Blogger()<cr>
|
||||
|
||||
if !exists('*s:Restify')
|
||||
python << EOF
|
||||
#{{{
|
||||
import os
|
||||
import sys
|
||||
import webbrowser
|
||||
|
||||
import vim
|
||||
|
||||
scriptdir = os.path.dirname(vim.eval('expand("<sfile>")'))
|
||||
sys.path.insert(0, scriptdir)
|
||||
try:
|
||||
from vimblogger.rest import blogPreview, blogArticleString
|
||||
from vimblogger.blogger import VimBlogger
|
||||
except ImportError:
|
||||
print "Plugin blogger cannot be loaded, due to lack of required modules"
|
||||
#}}}
|
||||
EOF
|
||||
|
||||
" Translate reSt text into html fragment suitable for preview in browser.
|
||||
fun <SID>Restify()
|
||||
python << EOF
|
||||
# {{{
|
||||
bufcontent = "\n".join(vim.current.buffer)
|
||||
name = vim.current.buffer.name
|
||||
|
||||
name = name[:-4] + ".html"
|
||||
html = blogPreview(bufcontent)
|
||||
output_file = open(name, "w")
|
||||
output_file.write(html)
|
||||
output_file.close()
|
||||
if vim.eval("g:blogger_browser"):
|
||||
webbrowser.open(name)
|
||||
print "Generated HTML has been opened in browser"
|
||||
else:
|
||||
print "Generated HTML has been written to %s" % name
|
||||
#}}}
|
||||
EOF
|
||||
endfun
|
||||
|
||||
" Generate headless html, gather title, dates and tags from filed list and
|
||||
" then send it to blog.
|
||||
fun <SID>Rst2Blogger()
|
||||
python << EOF
|
||||
#{{{
|
||||
bufcontent = "\n".join(vim.current.buffer)
|
||||
name = vim.current.buffer.name
|
||||
html, attrs = blogArticleString(bufcontent)
|
||||
|
||||
login = vim.eval("g:blogger_login")
|
||||
password = vim.eval("g:blogger_pass")
|
||||
blogname = vim.eval("g:blogger_name")
|
||||
|
||||
if not password:
|
||||
password = vim.eval('inputsecret("Enter your gmail password: ")')
|
||||
|
||||
title = 'title' in attrs and attrs['title'] or None
|
||||
date = 'date' in attrs and attrs['date'] or None
|
||||
tags = 'tags' in attrs and attrs['tags'] or ""
|
||||
tags = [tag.strip() for tag in tags.split(',')]
|
||||
modified = 'modified' in attrs and attrs['modified'] or None
|
||||
|
||||
blog = VimBlogger(blogname, login, password)
|
||||
print blog.create_article(title, html, tags=tags)
|
||||
|
||||
#}}}
|
||||
EOF
|
||||
endfun
|
||||
endif
|
||||
@@ -9,3 +9,7 @@ setlocal formatoptions=tcq "set VIms default
|
||||
let g:blogger_login="gryf73"
|
||||
let g:blogger_name="rdobosz"
|
||||
let g:blogger_browser=1
|
||||
let g:blogger_stylesheets=["css/widget_css_2_bundle.css", "css/style_custom.css", "css/style_blogger.css"]
|
||||
|
||||
map <F6> :PreviewBlogArticle<cr>
|
||||
map <F7> :SendBlogArticle<cr>
|
||||
|
||||
1
ftplugin/rst/rst2blogger/__init__.py
Normal file
1
ftplugin/rst/rst2blogger/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# module vimblogger
|
||||
258
ftplugin/rst/rst2blogger/blogger.py
Normal file
258
ftplugin/rst/rst2blogger/blogger.py
Normal file
@@ -0,0 +1,258 @@
|
||||
# vim: fileencoding=utf8
|
||||
#
|
||||
# Blogger interface to make easy way to create/update articles for specified
|
||||
# blog.
|
||||
#
|
||||
# It is assumed one way communication only, so you may create or update an
|
||||
# article from reST source files. There is no way to recreate article from
|
||||
# html to reST format.
|
||||
#
|
||||
# requirements:
|
||||
#
|
||||
# - Vim compiled with +python
|
||||
# - python 2.x (tested with 2.6)
|
||||
# - modules
|
||||
# - gdata (http://code.google.com/p/gdata-python-client)
|
||||
# - docutils (http://docutils.sourceforge.net)
|
||||
#
|
||||
# USE CASES:
|
||||
# 1. Create new post
|
||||
#
|
||||
# use reST template:
|
||||
# ===8<---
|
||||
# :Title: Blog post title
|
||||
# :Date: optional publish date (for example: 2010-11-28 18:47:05),
|
||||
# default: now()
|
||||
# :Modified: optional, default: None
|
||||
# :Tags: comma separated blog tags
|
||||
#
|
||||
# .. more
|
||||
#
|
||||
# --->8===
|
||||
#
|
||||
# All four docinfo are optional, however it is nice to give at least a title
|
||||
# to the article :)
|
||||
#
|
||||
#
|
||||
#
|
||||
# which is provided under templates directory or as a
|
||||
# snipMate shoortcut (see .vim/snippets/rst.snippets)
|
||||
#
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
#
|
||||
import datetime
|
||||
import re
|
||||
|
||||
import atom
|
||||
from gdata.blogger.client import BloggerClient, BLOG_POST_URL
|
||||
from gdata.blogger.data import BlogPost
|
||||
|
||||
|
||||
class VimBlogger(object):
|
||||
"""
|
||||
"""
|
||||
DATE_PATTERN = re.compile(r"^(\d{4}-\d{2}-\d{2})"
|
||||
"T(\d{2}:\d{2}:\d{2})(\.\d{3})?[+-]"
|
||||
"(\d{2}:\d{2})$")
|
||||
DATE_FORMAT = "%Y-%m-%d"
|
||||
TIME_FORMAT = "%H:%M:%S"
|
||||
TZ_FORMAT = "%H:%M"
|
||||
|
||||
# TODO: dodać usuwanie artykułów (prosta lista, wybieramy art,
|
||||
# potwierdzamy)
|
||||
# TODO: Dokumentacja jako vimdoc!
|
||||
|
||||
def __init__(self, blogname, login, password):
|
||||
"""
|
||||
"""
|
||||
self.draft = True
|
||||
self.blog_id = None
|
||||
self.blog = None
|
||||
self.client = BloggerClient()
|
||||
self._authorize(login, password)
|
||||
|
||||
self.feed = self.client.get_blogs()
|
||||
self._set_blog(blogname)
|
||||
|
||||
def get_articles(self, maxarticles=0):
|
||||
"""
|
||||
Return list of articles
|
||||
"""
|
||||
|
||||
feed = self.client.get_posts(self.blog_id)
|
||||
posts = []
|
||||
|
||||
for index, entry in enumerate(feed.entry):
|
||||
if maxarticles and index >= maxarticles:
|
||||
break
|
||||
posts.append((entry.get_post_id(),
|
||||
entry.title.text,
|
||||
self._extract_date(entry.published.text)))
|
||||
return posts
|
||||
|
||||
|
||||
def create_article(self, html_doc, attrs=None):
|
||||
"""
|
||||
Create new article
|
||||
html_doc is content of the article in HTML format, without headers,
|
||||
preamble, doctype and body tags.
|
||||
attrs is a dictionary that should hold title, date and tags.
|
||||
return BlogPost object
|
||||
"""
|
||||
if not attrs:
|
||||
attrs = {}
|
||||
|
||||
title = 'title' in attrs and attrs['title'] or ""
|
||||
title = atom.data.Title(text=title, type="text")
|
||||
html_doc = atom.data.Content(text=html_doc, type="html")
|
||||
|
||||
new_post = BlogPost(title=title, content=html_doc)
|
||||
|
||||
if 'tags' in attrs and attrs['tags']:
|
||||
for tag in attrs['tags'].split(','):
|
||||
new_post.add_label(tag.strip())
|
||||
|
||||
if 'date' in attrs and attrs['date'] and \
|
||||
self._check_date(attrs['date']):
|
||||
new_post.published = atom.data.Published(text=attrs['date'])
|
||||
|
||||
if self.draft:
|
||||
new_post.control = atom.data.Control(\
|
||||
draft=atom.data.Draft(text='yes'))
|
||||
|
||||
return self.client.post(new_post, BLOG_POST_URL % self.blog_id)
|
||||
|
||||
def update_article(self, html_doc, attrs):
|
||||
"""
|
||||
Update article.
|
||||
html_doc is content of the article in HTML format, without headers,
|
||||
preamble, doctype and body tags.
|
||||
attrs is a dictionary that should hold title, date and tags.
|
||||
return BlogPost object
|
||||
"""
|
||||
if "id" not in attrs:
|
||||
raise Exception("Post Id not found in attributes!")
|
||||
|
||||
post = self._get_post(attrs['id'])
|
||||
post.content = atom.data.Content(text=html_doc, type="html")
|
||||
|
||||
# update publish date
|
||||
if 'date' in attrs and attrs['date'] and \
|
||||
self._check_date(attrs['date']):
|
||||
post.published = atom.data.Published(text=attrs['date'])
|
||||
|
||||
if 'title' in attrs and attrs['title']:
|
||||
post.title = atom.data.Title(text=attrs['title'], type="text")
|
||||
#
|
||||
# update tag list
|
||||
if 'tags' in attrs:
|
||||
tags = [tag.strip() for tag in attrs['tags'].split(',')]
|
||||
for index, label in enumerate(post.category):
|
||||
if label.term not in tags:
|
||||
del(post.category[index])
|
||||
|
||||
for tag in tags:
|
||||
self._add_tag(post, tag.strip())
|
||||
|
||||
return self.client.update(post)
|
||||
|
||||
def delete_article(self, post_id):
|
||||
"""
|
||||
Delete selected article
|
||||
"""
|
||||
if not post_id:
|
||||
return "No article id provided"
|
||||
|
||||
post = self._get_post(post_id)
|
||||
self.client.delete(post)
|
||||
return None
|
||||
|
||||
|
||||
def _get_post(self, post_id):
|
||||
"""
|
||||
"""
|
||||
post_href = self.blog.get_post_link().href
|
||||
return self.client.get_feed(post_href + "/%s" % post_id,
|
||||
desired_class=BlogPost)
|
||||
|
||||
def _add_tag(self, post, tag):
|
||||
"""
|
||||
post - BlogPost object
|
||||
tag - string with tag/label to add
|
||||
"""
|
||||
for label in post.category:
|
||||
if label.term == tag:
|
||||
return
|
||||
|
||||
post.add_label(tag)
|
||||
|
||||
def _extract_date(self, date_string, time=False):
|
||||
"""
|
||||
Extract date from the string and optionally time
|
||||
"""
|
||||
|
||||
if not self.DATE_PATTERN.match(date_string):
|
||||
return False
|
||||
|
||||
if not time:
|
||||
return self.DATE_PATTERN.match(date_string).groups()[0]
|
||||
|
||||
groups = self.DATE_PATTERN.match(date_string).groups()
|
||||
return groups[0] + " " + groups[1]
|
||||
|
||||
def _check_date(self, date):
|
||||
"""
|
||||
Parse date as RFC 3339 format, for example:
|
||||
2010-11-30T21:06:48.678+01:00
|
||||
or
|
||||
2010-11-30T21:06:48+01:00
|
||||
|
||||
Returns true, if date is acceptable, false otherwise
|
||||
"""
|
||||
if not self.DATE_PATTERN.match(date):
|
||||
return False
|
||||
|
||||
groups = self.DATE_PATTERN.match(date).groups()
|
||||
_date = groups[0]
|
||||
_time = groups[1]
|
||||
_tz = len(groups) == 3 and groups[2] or groups[3]
|
||||
|
||||
try:
|
||||
datetime.datetime.strptime(_date, self.DATE_FORMAT)
|
||||
datetime.datetime.strptime(_time, self.TIME_FORMAT)
|
||||
datetime.datetime.strptime(_tz, self.TZ_FORMAT)
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def _update_date(self, post, attrs):
|
||||
"""
|
||||
Update articles published date
|
||||
"""
|
||||
|
||||
def _authorize(self, login, password):
|
||||
"""
|
||||
Try to authorize in Google service.
|
||||
Authorization is kept in client object. In case of wrong credentials,
|
||||
exception is thrown.
|
||||
"""
|
||||
source = 'Blogger_Python_Sample-2.0'
|
||||
service = 'blogger'
|
||||
|
||||
self.client.client_login(login,
|
||||
password,
|
||||
source=source,
|
||||
service=service)
|
||||
|
||||
def _set_blog(self, blogname):
|
||||
"""
|
||||
Set correct blog, as defined in blogname
|
||||
"""
|
||||
for blog in self.feed.entry:
|
||||
if blog.get_blog_name() == blogname:
|
||||
self.blog_id = blog.get_blog_id()
|
||||
self.blog = blog
|
||||
break
|
||||
|
||||
197
ftplugin/rst/rst2blogger/main.py
Normal file
197
ftplugin/rst/rst2blogger/main.py
Normal file
@@ -0,0 +1,197 @@
|
||||
# vim: fileencoding=utf8
|
||||
import webbrowser
|
||||
from xml.dom import minidom
|
||||
from xml.parsers.expat import ExpatError
|
||||
|
||||
import vim
|
||||
|
||||
from rst2blogger.rest import blogPreview, blogArticleString
|
||||
from rst2blogger.blogger import VimBlogger
|
||||
|
||||
|
||||
class Rst2Blogger(object):
|
||||
"""
|
||||
Provide convenient way to communicate between vim and blogger through reST
|
||||
"""
|
||||
def __init__(self):
|
||||
vim.command('call setqflist([])')
|
||||
|
||||
self.buff = vim.current.buffer
|
||||
self.docinfo_len = 0
|
||||
self._set_docinfo_len()
|
||||
self.login = vim.eval("g:blogger_login")
|
||||
self.password = vim.eval("g:blogger_pass")
|
||||
self.blogname = vim.eval("g:blogger_name")
|
||||
self.buffer_encoding = vim.eval("&fileencoding")
|
||||
self.vim_encoding = vim.eval("&encoding")
|
||||
self.draft = int(vim.eval("g:blogger_draft"))
|
||||
self.maxarticles = int(vim.eval("g:blogger_maxarticles"))
|
||||
self.confirm_del = int(vim.eval("g:blogger_confirm_del"))
|
||||
self.stylesheets = vim.eval("g:blogger_stylesheets")
|
||||
|
||||
def preview(self):
|
||||
"""
|
||||
Generate HTML Blogger article preview and (optionally) display it in
|
||||
systems' web browser
|
||||
"""
|
||||
bufcontent = "\n".join(self.buff)
|
||||
name = vim.current.buffer.name
|
||||
|
||||
name = name[:-4] + ".html"
|
||||
html = blogPreview(bufcontent, self.stylesheets)
|
||||
self._open_qf(self._check_html(html))
|
||||
|
||||
output_file = open(name, "w")
|
||||
output_file.write(html)
|
||||
output_file.close()
|
||||
if vim.eval("g:blogger_browser"):
|
||||
webbrowser.open(name)
|
||||
return "Generated HTML has been opened in browser"
|
||||
else:
|
||||
return "Generated HTML has been written to %s" % name
|
||||
|
||||
def post(self):
|
||||
bufcontent = "\n".join(vim.current.buffer)
|
||||
html, attrs = blogArticleString(bufcontent)
|
||||
|
||||
parse_msg = self._check_html(html, True)
|
||||
if parse_msg:
|
||||
self._open_qf(parse_msg)
|
||||
return "There are errors in generated document"
|
||||
|
||||
if not self.password:
|
||||
self.password = vim.eval('inputsecret("Enter your gmail password: ")')
|
||||
|
||||
blog = VimBlogger(self.blogname, self.login, self.password)
|
||||
blog.draft = self.draft > 0
|
||||
|
||||
if 'id' in attrs and attrs['id']:
|
||||
post = blog.update_article(html, attrs=attrs)
|
||||
msg = unicode("Article '%s' has been updated" % post.title.text)
|
||||
msg = msg.encode(self.vim_encoding)
|
||||
else:
|
||||
post = blog.create_article(html, attrs=attrs)
|
||||
msg = "New article with id %s has been created" % \
|
||||
post.get_post_id()
|
||||
|
||||
if not post:
|
||||
return "There is something fishy with creating new article."
|
||||
|
||||
for item, value in (('id', post.get_post_id()),
|
||||
('date', post.published.text),
|
||||
('title', post.title.text),
|
||||
('modified', post.updated.text),
|
||||
('tags',
|
||||
", ".join([cat.term for cat in post.category]))):
|
||||
self._update_docinfo(item, value)
|
||||
return msg
|
||||
|
||||
def delete(self):
|
||||
"""
|
||||
Get list of articles, display it to the user, make him choose one and
|
||||
delete
|
||||
"""
|
||||
if not self.password:
|
||||
self.password = vim.eval('inputsecret("Enter your gmail password: ")')
|
||||
blog = VimBlogger(self.blogname, self.login, self.password)
|
||||
|
||||
posts = blog.get_articles(self.maxarticles)
|
||||
|
||||
msg = u"inputlist(["
|
||||
for index, entries in enumerate(posts):
|
||||
line = "%2d %s %s" % (index+1,
|
||||
entries[1],
|
||||
entries[2])
|
||||
msg += u'"' + line.replace('"', '\\"') + u'",'
|
||||
msg = msg[:-1]
|
||||
msg += u"])"
|
||||
msg = unicode(msg).encode(self.vim_encoding)
|
||||
|
||||
choice = int(vim.eval(msg))
|
||||
if choice:
|
||||
art = posts[choice-1]
|
||||
msg = 'confirm("You are about to delete article \'%s\'. Are you sure?"'
|
||||
msg = unicode(msg % art[1]).encode(self.vim_encoding)
|
||||
msg += ', "&No\n&Yes")'
|
||||
|
||||
if self.confirm_del:
|
||||
choice = int(vim.eval(msg))
|
||||
else:
|
||||
choice = 2
|
||||
|
||||
if choice == 2:
|
||||
result = blog.delete_article(art[0])
|
||||
if result is None:
|
||||
return "Article deleted"
|
||||
else:
|
||||
return result
|
||||
return "No articles deleted"
|
||||
|
||||
|
||||
def _update_docinfo(self, attr, val):
|
||||
"""
|
||||
Update current buffer with attributes value
|
||||
"""
|
||||
|
||||
val = unicode(":%s: %s" % (attr.capitalize(), val))
|
||||
val = val.encode(self.buffer_encoding)
|
||||
|
||||
if not self.docinfo_len:
|
||||
self.buff.append(val, 0)
|
||||
return
|
||||
|
||||
for num, line in enumerate(self.buff[:self.docinfo_len]):
|
||||
if ':%s:' % attr in line.lower() and line.startswith(":"):
|
||||
self.buff[num] = val
|
||||
return
|
||||
|
||||
self.buff.append(val, 0)
|
||||
self.docinfo_len += 1
|
||||
|
||||
def _set_docinfo_len(self):
|
||||
"""
|
||||
Set docinfo_len, which means number of lines from the beginning of the
|
||||
buffer to the first empty line.
|
||||
"""
|
||||
for num, line in enumerate(self.buff):
|
||||
if line and line.startswith(':'):
|
||||
continue
|
||||
elif not line:
|
||||
self.docinfo_len = num
|
||||
break
|
||||
else:
|
||||
self.docinfo_len = 0
|
||||
break
|
||||
|
||||
def _open_qf(self, msg):
|
||||
"""
|
||||
Open VIm QuickFix window with message, if argument msg is non empty
|
||||
string.
|
||||
"""
|
||||
if msg:
|
||||
msg1 = "There are problems reported by XML parser:"
|
||||
msg2 = "Check generated html for errors."
|
||||
vim.command('call setqflist([{"text": "%s"}, {"text": "%s"}, '
|
||||
'{"text": "%s"}])' % (msg1, msg, msg2))
|
||||
vim.command('copen')
|
||||
|
||||
def _check_html(self, html, add_container=False):
|
||||
"""
|
||||
Check HTML generated document, by simply use minidom parser
|
||||
If add_container is set to True, entire document is wrapped inside
|
||||
additional div
|
||||
returns empty string if parses succeed, else exception message.
|
||||
"""
|
||||
|
||||
if add_container:
|
||||
html = "<div>" + html + "</div>"
|
||||
|
||||
message = ""
|
||||
try:
|
||||
minidom.parseString(html)
|
||||
except ExpatError as ex:
|
||||
message = str(ex)
|
||||
|
||||
return message
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ class Attrs(object):
|
||||
|
||||
class Pygments(Directive):
|
||||
"""
|
||||
Source code syntax hightlighting.
|
||||
Source code syntax highlighting.
|
||||
"""
|
||||
required_arguments = 1
|
||||
optional_arguments = 0
|
||||
@@ -72,7 +72,7 @@ class CustomHTMLTranslator(HTMLTranslator):
|
||||
|
||||
def depart_docinfo(self, node):
|
||||
"""
|
||||
Reset body, remove unnecesairy content.
|
||||
Reset body, remove unnecessary content.
|
||||
"""
|
||||
self.body = []
|
||||
|
||||
@@ -165,8 +165,7 @@ class NoHeaderHTMLTranslator(CustomHTMLTranslator):
|
||||
Harvest docinfo fields and store it in global dictionary.
|
||||
"""
|
||||
key, val = [n.astext() for n in node]
|
||||
key = key.lower()
|
||||
Attrs.ATTRS[key] = val
|
||||
Attrs.ATTRS[key.lower()] = val.strip()
|
||||
|
||||
def visit_date(self, node):
|
||||
"""
|
||||
@@ -176,8 +175,9 @@ class NoHeaderHTMLTranslator(CustomHTMLTranslator):
|
||||
|
||||
class PreviewHTMLTranslator(CustomHTMLTranslator):
|
||||
"""
|
||||
Class for dislpay article in the browser as a preview.
|
||||
Class for display article in the browser as a preview.
|
||||
"""
|
||||
CSS = []
|
||||
def __init__(self, document):
|
||||
"""
|
||||
Alter levels for the heading tags, define custom, blog specific
|
||||
@@ -188,9 +188,7 @@ class PreviewHTMLTranslator(CustomHTMLTranslator):
|
||||
self.initial_header_level = 1
|
||||
self.section_level = 1
|
||||
# order of css files is important
|
||||
self.default_stylesheets = ["css/widget_css_2_bundle.css",
|
||||
"css/style_custom.css",
|
||||
"css/style_blogger.css"]
|
||||
self.default_stylesheets = PreviewHTMLTranslator.CSS
|
||||
self.stylesheet = [self.stylesheet_link % self.encode(css) \
|
||||
for css in self.default_stylesheets]
|
||||
self.body_ = []
|
||||
@@ -230,21 +228,27 @@ class BlogPreviewWriter(Writer):
|
||||
"""
|
||||
Custom Writer class for generating full HTML of the article
|
||||
"""
|
||||
def __init__(self):
|
||||
def __init__(self, stylesheets=None):
|
||||
Writer.__init__(self)
|
||||
if not stylesheets:
|
||||
stylesheets = []
|
||||
self.translator_class = PreviewHTMLTranslator
|
||||
self.translator_class.CSS = stylesheets
|
||||
|
||||
def translate(self):
|
||||
self.document.settings.output_encoding = "utf-8"
|
||||
Writer.translate(self)
|
||||
|
||||
|
||||
def blogPreview(string):
|
||||
def blogPreview(string, stylesheets=None):
|
||||
"""
|
||||
Returns partial HTML of the article, and attribute dictionary
|
||||
Returns full HTML of the article.
|
||||
string argument is an article in reST
|
||||
"""
|
||||
html_output = core.publish_string(string, writer=BlogPreviewWriter())
|
||||
if not stylesheets:
|
||||
stylesheets = []
|
||||
html_output = core.publish_string(string,
|
||||
writer=BlogPreviewWriter(stylesheets))
|
||||
html_output = html_output.strip()
|
||||
html_output = html_output.replace("<!-- more -->", "\n<!-- more -->\n")
|
||||
return html_output
|
||||
@@ -259,5 +263,10 @@ def blogArticleString(string):
|
||||
html_output = core.publish_string(string, writer=BlogBodyWriter())
|
||||
html_output = html_output.strip()
|
||||
html_output = html_output.replace("<!-- more -->", "\n<!-- more -->\n")
|
||||
return html_output, Attrs.ATTRS
|
||||
attrs = {}
|
||||
for key in Attrs.ATTRS:
|
||||
if Attrs.ATTRS[key]:
|
||||
attrs[key] = Attrs.ATTRS[key]
|
||||
|
||||
return html_output, attrs
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
# vim: fileencoding=utf8
|
||||
#
|
||||
# Blogger interface to make easy way to create/update articles for specified
|
||||
# blog.
|
||||
#
|
||||
# It is assumed one way communication only, so you may create or update an
|
||||
# article from reST source files. There is no way to recreate article from
|
||||
# html to reST format.
|
||||
#
|
||||
# requirements:
|
||||
#
|
||||
# - Vim compiled with +python
|
||||
# - python 2.x (tested with 2.6)
|
||||
# - modules
|
||||
# - gdata (http://code.google.com/p/gdata-python-client)
|
||||
# - docutils (http://docutils.sourceforge.net)
|
||||
# - pytz (http://pytz.sourceforge.net)
|
||||
#
|
||||
# USE CASES:
|
||||
# 1. Create new post
|
||||
#
|
||||
# use reST template:
|
||||
# ===8<---
|
||||
# :Title: Blog post title
|
||||
# :Date: optional publish date (for example: 2010-11-28 18:47:05),
|
||||
# default: now()
|
||||
# :Modified: optional, default: None
|
||||
# :Tags: comma separated blog tags
|
||||
#
|
||||
# .. more
|
||||
#
|
||||
# --->8===
|
||||
#
|
||||
# All four docinfo are optional, however it is nice to give at least a title
|
||||
# to the article :)
|
||||
#
|
||||
#
|
||||
#
|
||||
# which is provided under templates directory or as a
|
||||
# snipMate shoortcut (see .vim/snippets/rst.snippets)
|
||||
#
|
||||
|
||||
# vim.eval('inputsecret("Password: ")')
|
||||
# echomsg expand("%:p")
|
||||
#-----------------------------------------------------------------------------
|
||||
#
|
||||
import getpass # TODO: remove
|
||||
import time
|
||||
import datetime
|
||||
|
||||
import pytz
|
||||
import atom
|
||||
from gdata.blogger.client import BloggerClient
|
||||
|
||||
|
||||
class VimBlogger(object):
|
||||
"""
|
||||
"""
|
||||
|
||||
def __init__(self, blogname, login, password):
|
||||
"""
|
||||
"""
|
||||
self.blog = None
|
||||
self.client = BloggerClient()
|
||||
self._authorize(login, password)
|
||||
|
||||
self.feed = self.client.get_blogs()
|
||||
self._set_blog(blogname)
|
||||
#self._get_arts(blogname)
|
||||
|
||||
def _set_blog(self, blogname):
|
||||
"""
|
||||
"""
|
||||
for blog in self.feed.entry:
|
||||
if blog.get_blog_name() == blogname:
|
||||
self.blog = blog
|
||||
break
|
||||
|
||||
|
||||
def _get_arts(self, blogname):
|
||||
"""
|
||||
"""
|
||||
feed = self.client.get_posts(self.blog.get_blog_id())
|
||||
for entry in feed.entry:
|
||||
print entry.title.text
|
||||
#
|
||||
import ipdb; ipdb.set_trace()
|
||||
#
|
||||
# entry.content obiekt zawiera ciało artykułu (entry.content.text
|
||||
# posiada czystą formę która mnie interesuje najbardziej, do której
|
||||
# można pisać
|
||||
#
|
||||
# entry.category - lista wszystkich kategorii (blogowych tagów), które
|
||||
# post posiada. Są to elementy klasy atom.data.Category, które
|
||||
# łatwiutko stworzyć i dodać do posta:
|
||||
# import atom
|
||||
# cat1 = atom.data.Category()
|
||||
# cat1.term = "nowy tag dla bloggera"
|
||||
# entry.category.append(cat1)
|
||||
#
|
||||
# entry.title przechowuje tytuł posta
|
||||
|
||||
def _authorize(self, login, password):
|
||||
"""
|
||||
"""
|
||||
source = 'Blogger_Python_Sample-2.0'
|
||||
service = 'blogger'
|
||||
|
||||
self.client.client_login(login,
|
||||
password,
|
||||
source=source,
|
||||
service=service)
|
||||
def create_article(self, title, html_doc, tags=None):
|
||||
"""
|
||||
"""
|
||||
|
||||
blog_id = self.blog.get_blog_id()
|
||||
if tags is None:
|
||||
tags = []
|
||||
return self.client.add_post(blog_id, title, html_doc, labels=tags,
|
||||
draft=True)
|
||||
|
||||
def update_article(self, title, html_doc, tags=None):
|
||||
"""
|
||||
"""
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
p = getpass.getpass("Password: ")
|
||||
b = VimBlogger("rdobosz", "gryf73@gmail.com", p)
|
||||
72
ftplugin/rst/vimblogger_ft.vim
Normal file
72
ftplugin/rst/vimblogger_ft.vim
Normal file
@@ -0,0 +1,72 @@
|
||||
" reST to blogger vim interface.
|
||||
" Provide some convinient commands for creating preview from the reST file
|
||||
" and to send articles to blog.
|
||||
|
||||
if exists("b:did_rst_plugin")
|
||||
finish " load only once
|
||||
else
|
||||
let b:did_blogger_plugin = 1
|
||||
endif
|
||||
|
||||
if exists(':PreviewBlogArticle')
|
||||
finish
|
||||
endif
|
||||
|
||||
if !exists("g:blogger_browser")
|
||||
let g:blogger_browser = 0
|
||||
endif
|
||||
|
||||
if !exists("g:blogger_name")
|
||||
let g:blogger_name = ""
|
||||
endif
|
||||
|
||||
if !exists("g:blogger_login")
|
||||
let g:blogger_login= ""
|
||||
endif
|
||||
|
||||
if !exists("g:blogger_pass")
|
||||
let g:blogger_pass = "Kurcz4czek"
|
||||
endif
|
||||
|
||||
if !exists("g:blogger_draft")
|
||||
let g:blogger_draft = 1
|
||||
endif
|
||||
|
||||
if !exists("g:blogger_maxarticles")
|
||||
let g:blogger_maxarticles = 0
|
||||
endif
|
||||
|
||||
if !exists("g:blogger_confirm_del")
|
||||
let g:blogger_confirm_del = 1
|
||||
endif
|
||||
|
||||
if !exists("g:blogger_stylesheets")
|
||||
let g:blogger_stylesheets = []
|
||||
endif
|
||||
|
||||
python << EOF
|
||||
import os
|
||||
import sys
|
||||
|
||||
import vim
|
||||
|
||||
scriptdir = os.path.dirname(vim.eval('expand("<sfile>")'))
|
||||
sys.path.insert(0, scriptdir)
|
||||
|
||||
try:
|
||||
from rst2blogger.main import Rst2Blogger
|
||||
except ImportError:
|
||||
print "Plugin vimblogger cannot be loaded, due to lack of required modules"
|
||||
EOF
|
||||
|
||||
if !exists(":PreviewBlogArticle")
|
||||
command PreviewBlogArticle py print Rst2Blogger().preview()
|
||||
endif
|
||||
|
||||
if !exists(":SendBlogArticle")
|
||||
command SendBlogArticle py print Rst2Blogger().post()
|
||||
endif
|
||||
|
||||
if !exists(":DeleteBlogArticle")
|
||||
command DeleteBlogArticle py print Rst2Blogger().delete()
|
||||
endif
|
||||
170
plugin/acp.vim
170
plugin/acp.vim
@@ -1,170 +0,0 @@
|
||||
"=============================================================================
|
||||
" Copyright (c) 2007-2009 Takeshi NISHIDA
|
||||
"
|
||||
" GetLatestVimScripts: 1879 1 :AutoInstall: AutoComplPop
|
||||
"=============================================================================
|
||||
" LOAD GUARD {{{1
|
||||
|
||||
if exists('g:loaded_acp')
|
||||
finish
|
||||
elseif v:version < 702
|
||||
echoerr 'AutoComplPop does not support this version of vim (' . v:version . ').'
|
||||
finish
|
||||
endif
|
||||
let g:loaded_acp = 1
|
||||
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
" FUNCTION: {{{1
|
||||
|
||||
"
|
||||
function s:defineOption(name, default)
|
||||
if !exists(a:name)
|
||||
let {a:name} = a:default
|
||||
endif
|
||||
endfunction
|
||||
|
||||
"
|
||||
function s:makeDefaultBehavior()
|
||||
let behavs = {
|
||||
\ '*' : [],
|
||||
\ 'ruby' : [],
|
||||
\ 'python' : [],
|
||||
\ 'perl' : [],
|
||||
\ 'xml' : [],
|
||||
\ 'html' : [],
|
||||
\ 'xhtml' : [],
|
||||
\ 'css' : [],
|
||||
\ }
|
||||
"---------------------------------------------------------------------------
|
||||
if !empty(g:acp_behaviorUserDefinedFunction) &&
|
||||
\ !empty(g:acp_behaviorUserDefinedMeets)
|
||||
for key in keys(behavs)
|
||||
call add(behavs[key], {
|
||||
\ 'command' : "\<C-x>\<C-u>",
|
||||
\ 'completefunc' : g:acp_behaviorUserDefinedFunction,
|
||||
\ 'meets' : g:acp_behaviorUserDefinedMeets,
|
||||
\ 'repeat' : 0,
|
||||
\ })
|
||||
endfor
|
||||
endif
|
||||
"---------------------------------------------------------------------------
|
||||
for key in keys(behavs)
|
||||
call add(behavs[key], {
|
||||
\ 'command' : "\<C-x>\<C-u>",
|
||||
\ 'completefunc' : 'acp#completeSnipmate',
|
||||
\ 'meets' : 'acp#meetsForSnipmate',
|
||||
\ 'onPopupClose' : 'acp#onPopupCloseSnipmate',
|
||||
\ 'repeat' : 0,
|
||||
\ })
|
||||
endfor
|
||||
"---------------------------------------------------------------------------
|
||||
for key in keys(behavs)
|
||||
call add(behavs[key], {
|
||||
\ 'command' : g:acp_behaviorKeywordCommand,
|
||||
\ 'meets' : 'acp#meetsForKeyword',
|
||||
\ 'repeat' : 0,
|
||||
\ })
|
||||
endfor
|
||||
"---------------------------------------------------------------------------
|
||||
for key in keys(behavs)
|
||||
call add(behavs[key], {
|
||||
\ 'command' : "\<C-x>\<C-f>",
|
||||
\ 'meets' : 'acp#meetsForFile',
|
||||
\ 'repeat' : 1,
|
||||
\ })
|
||||
endfor
|
||||
"---------------------------------------------------------------------------
|
||||
call add(behavs.ruby, {
|
||||
\ 'command' : "\<C-x>\<C-o>",
|
||||
\ 'meets' : 'acp#meetsForRubyOmni',
|
||||
\ 'repeat' : 0,
|
||||
\ })
|
||||
"---------------------------------------------------------------------------
|
||||
call add(behavs.python, {
|
||||
\ 'command' : "\<C-x>\<C-o>",
|
||||
\ 'meets' : 'acp#meetsForPythonOmni',
|
||||
\ 'repeat' : 0,
|
||||
\ })
|
||||
"---------------------------------------------------------------------------
|
||||
call add(behavs.perl, {
|
||||
\ 'command' : "\<C-x>\<C-o>",
|
||||
\ 'meets' : 'acp#meetsForPerlOmni',
|
||||
\ 'repeat' : 0,
|
||||
\ })
|
||||
"---------------------------------------------------------------------------
|
||||
call add(behavs.xml, {
|
||||
\ 'command' : "\<C-x>\<C-o>",
|
||||
\ 'meets' : 'acp#meetsForXmlOmni',
|
||||
\ 'repeat' : 1,
|
||||
\ })
|
||||
"---------------------------------------------------------------------------
|
||||
call add(behavs.html, {
|
||||
\ 'command' : "\<C-x>\<C-o>",
|
||||
\ 'meets' : 'acp#meetsForHtmlOmni',
|
||||
\ 'repeat' : 1,
|
||||
\ })
|
||||
"---------------------------------------------------------------------------
|
||||
call add(behavs.xhtml, {
|
||||
\ 'command' : "\<C-x>\<C-o>",
|
||||
\ 'meets' : 'acp#meetsForHtmlOmni',
|
||||
\ 'repeat' : 1,
|
||||
\ })
|
||||
"---------------------------------------------------------------------------
|
||||
call add(behavs.css, {
|
||||
\ 'command' : "\<C-x>\<C-o>",
|
||||
\ 'meets' : 'acp#meetsForCssOmni',
|
||||
\ 'repeat' : 0,
|
||||
\ })
|
||||
"---------------------------------------------------------------------------
|
||||
return behavs
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
" INITIALIZATION {{{1
|
||||
|
||||
"-----------------------------------------------------------------------------
|
||||
call s:defineOption('g:acp_enableAtStartup', 1)
|
||||
call s:defineOption('g:acp_mappingDriven', 0)
|
||||
call s:defineOption('g:acp_ignorecaseOption', 1)
|
||||
call s:defineOption('g:acp_completeOption', '.,w,b,k')
|
||||
call s:defineOption('g:acp_completeoptPreview', 0)
|
||||
call s:defineOption('g:acp_behaviorUserDefinedFunction', '')
|
||||
call s:defineOption('g:acp_behaviorUserDefinedMeets', '')
|
||||
call s:defineOption('g:acp_behaviorSnipmateLength', -1)
|
||||
call s:defineOption('g:acp_behaviorKeywordCommand', "\<C-n>")
|
||||
call s:defineOption('g:acp_behaviorKeywordLength', 2)
|
||||
call s:defineOption('g:acp_behaviorKeywordIgnores', [])
|
||||
call s:defineOption('g:acp_behaviorFileLength', 0)
|
||||
call s:defineOption('g:acp_behaviorRubyOmniMethodLength', 0)
|
||||
call s:defineOption('g:acp_behaviorRubyOmniSymbolLength', 1)
|
||||
call s:defineOption('g:acp_behaviorPythonOmniLength', 0)
|
||||
call s:defineOption('g:acp_behaviorPerlOmniLength', -1)
|
||||
call s:defineOption('g:acp_behaviorXmlOmniLength', 0)
|
||||
call s:defineOption('g:acp_behaviorHtmlOmniLength', 0)
|
||||
call s:defineOption('g:acp_behaviorCssOmniPropertyLength', 1)
|
||||
call s:defineOption('g:acp_behaviorCssOmniValueLength', 0)
|
||||
call s:defineOption('g:acp_behavior', {})
|
||||
"-----------------------------------------------------------------------------
|
||||
call extend(g:acp_behavior, s:makeDefaultBehavior(), 'keep')
|
||||
"-----------------------------------------------------------------------------
|
||||
command! -bar -narg=0 AcpEnable call acp#enable()
|
||||
command! -bar -narg=0 AcpDisable call acp#disable()
|
||||
command! -bar -narg=0 AcpLock call acp#lock()
|
||||
command! -bar -narg=0 AcpUnlock call acp#unlock()
|
||||
"-----------------------------------------------------------------------------
|
||||
" legacy commands
|
||||
command! -bar -narg=0 AutoComplPopEnable AcpEnable
|
||||
command! -bar -narg=0 AutoComplPopDisable AcpDisable
|
||||
command! -bar -narg=0 AutoComplPopLock AcpLock
|
||||
command! -bar -narg=0 AutoComplPopUnlock AcpUnlock
|
||||
"-----------------------------------------------------------------------------
|
||||
if g:acp_enableAtStartup
|
||||
AcpEnable
|
||||
endif
|
||||
"-----------------------------------------------------------------------------
|
||||
|
||||
" }}}1
|
||||
"=============================================================================
|
||||
" vim: set fdm=marker:
|
||||
@@ -106,3 +106,11 @@ snippet docmodule
|
||||
"""
|
||||
snippet debug
|
||||
LOG.debug(self.${1:method_name}.__doc__.strip())
|
||||
snippet edbg
|
||||
import sys
|
||||
pydevdPath = r"/mnt/data/IDE/eclipse/plugins/org.python.pydev.debug_1.6.3.2010100513/pysrc"
|
||||
if not pydevdPath in sys.path:
|
||||
sys.path.append(pydevdPath)
|
||||
import pydevd
|
||||
pydevd.settrace()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user