From 0fc75c596c15443b07bb5c0e6a09b740e95bf780 Mon Sep 17 00:00:00 2001 From: Camille Dejoye Date: Sun, 7 Jun 2020 15:26:06 +0200 Subject: [PATCH] improvement: generalize the hook system It is still not possible to override an existing hook but with this system users can create new hooks really simply without having to update any configuration since they will be autodetected. The only missing thins is the possibility to disable hook, therefore it is the responsibility of each hook to provide a way to the user to use it or not. --- autoload/argwrap.vim | 8 ++- autoload/argwrap/hooks.vim | 45 +++++++++++++ .../php/200_smart_brace.vim} | 36 ++++++---- doc/argwrap.txt | 66 ++++++++++++++++++- plugin/argwrap.vim | 1 + 5 files changed, 140 insertions(+), 16 deletions(-) create mode 100644 autoload/argwrap/hooks.vim rename autoload/argwrap/hooks/{php.vim => filetype/php/200_smart_brace.vim} (66%) diff --git a/autoload/argwrap.vim b/autoload/argwrap.vim index dcb71bc..c620654 100644 --- a/autoload/argwrap.vim +++ b/autoload/argwrap.vim @@ -257,15 +257,19 @@ function! argwrap#toggle() let l:container = argwrap#extractContainer(l:range) if l:range.lineStart == l:range.lineEnd + call argwrap#hooks#execute('pre_wrap', l:range, l:container, l:arguments) + call argwrap#wrapContainer(l:range, l:container, l:arguments, l:wrapBrace, l:tailComma, l:tailCommaBraces, l:tailIndentBraces, l:linePrefix, l:commaFirst, l:commaFirstIndent) let l:cursor[1] = l:range.lineStart + 1 - silent! call argwrap#hooks#{&filetype}#post_wrap(l:range, l:container, l:arguments) + call argwrap#hooks#execute('post_wrap', l:range, l:container, l:arguments) else + call argwrap#hooks#execute('pre_unwrap', l:range, l:container, l:arguments) + call argwrap#unwrapContainer(l:range, l:container, l:arguments, l:padded) let l:cursor[1] = l:range.lineStart - silent! call argwrap#hooks#{&filetype}#post_unwrap(l:range, l:container, l:arguments) + call argwrap#hooks#execute('post_unwrap', l:range, l:container, l:arguments) endif call setpos('.', l:cursor) diff --git a/autoload/argwrap/hooks.vim b/autoload/argwrap/hooks.vim new file mode 100644 index 0000000..559fe76 --- /dev/null +++ b/autoload/argwrap/hooks.vim @@ -0,0 +1,45 @@ +function! s:loadGlobalHooks() abort " {{{ + if !exists('g:argwrap_global_hooks') + let g:argwrap_global_hooks = [] + + for hook in globpath(&runtimepath, 'autoload/argwrap/hooks/*.vim', 0, 1) + let l:filename = matchstr(hook, '\vhooks/\zs.+\ze\.vim$') + + call add(g:argwrap_global_hooks, printf('argwrap#hooks#%s', l:filename)) + endfor + endif + + return g:argwrap_global_hooks +endfunction " }}} + +function! s:loadFiletypeHooks(filetype) abort " {{{ + if !exists('g:argwrap_filetype_hooks.'.a:filetype) + let g:argwrap_filetype_hooks[a:filetype] = [] + let l:hooks = g:argwrap_filetype_hooks[a:filetype] + + for filetypeHook in globpath(&runtimepath, 'autoload/argwrap/hooks/filetype/*/*.vim', 0, 1) + let l:filetype = matchstr(filetypeHook, '\vhooks/filetype/\zs.+\ze/.+\.vim$') + let l:filename = matchstr(filetypeHook, '\vhooks/filetype/.+/\zs.+\ze\.vim$') + + call add(l:hooks, printf('argwrap#hooks#filetype#%s#%s', l:filetype, l:filename)) + endfor + endif + + return g:argwrap_filetype_hooks[a:filetype] +endfunction " }}} + +function! s:load() abort " {{{ + if !exists('b:argwrap_hooks') + let b:argwrap_hooks = s:loadGlobalHooks() + s:loadFiletypeHooks(&filetype) + endif + + return b:argwrap_hooks +endfunction " }}} + +function! argwrap#hooks#execute(name, ...) abort " {{{ + for hook in s:load() + silent! call call(printf('%s#%s', hook, a:name), a:000) + endfor +endfunction " }}} + +" vim: ts=2 sw=2 et fdm=marker diff --git a/autoload/argwrap/hooks/php.vim b/autoload/argwrap/hooks/filetype/php/200_smart_brace.vim similarity index 66% rename from autoload/argwrap/hooks/php.vim rename to autoload/argwrap/hooks/filetype/php/200_smart_brace.vim index e34902f..230ecdb 100644 --- a/autoload/argwrap/hooks/php.vim +++ b/autoload/argwrap/hooks/filetype/php/200_smart_brace.vim @@ -10,18 +10,6 @@ function! s:dealWithMethodArguments(container) abort " {{{ return 1 endfunction " }}} -function! argwrap#hooks#php#post_wrap(range, container, arguments) abort " {{{ - if argwrap#getSetting('php_smart_brace', 0) - call s:fixMethodOpeningBraceAfterWrap(a:range, a:container, a:arguments) - endif -endfunction " }}} - -function! argwrap#hooks#php#post_unwrap(range, container, arguments) abort " {{{ - if argwrap#getSetting('php_smart_brace', 0) - call s:fixMethodOpeningBraceAfterUnwrap(a:range, a:container, a:arguments) - endif -endfunction " }}} - function! s:fixMethodOpeningBraceAfterWrap(range, container, arguments) abort " {{{ if !s:dealWithMethodArguments(a:container) return @@ -57,4 +45,28 @@ function! s:fixMethodOpeningBraceAfterUnwrap(range, container, arguments) abort execute printf("undojoin | normal! %dG0%dlct{\", a:range.lineStart, l:col) endfunction " }}} +function! argwrap#hooks#filetype#php#200_smart_brace#pre_wrap(range, container, arguments) abort " {{{ + " Do nothing but prevent the file to be loaded more than once + " When calling an autoload function that is not define the script that + " should contain it is sourced every time the function is called +endfunction " }}} + +function! argwrap#hooks#filetype#php#200_smart_brace#pre_unwrap(range, container, arguments) abort " {{{ + " Do nothing but prevent the file to be loaded more than once + " When calling an autoload function that is not define the script that + " should contain it is sourced every time the function is called +endfunction " }}} + +function! argwrap#hooks#filetype#php#200_smart_brace#post_wrap(range, container, arguments) abort " {{{ + if argwrap#getSetting('php_smart_brace', 0) + call s:fixMethodOpeningBraceAfterWrap(a:range, a:container, a:arguments) + endif +endfunction " }}} + +function! argwrap#hooks#filetype#php#200_smart_brace#post_unwrap(range, container, arguments) abort " {{{ + if argwrap#getSetting('php_smart_brace', 0) + call s:fixMethodOpeningBraceAfterUnwrap(a:range, a:container, a:arguments) + endif +endfunction " }}} + " vim: ts=2 sw=2 et fdm=marker diff --git a/doc/argwrap.txt b/doc/argwrap.txt index e76b1b8..8ca10f1 100644 --- a/doc/argwrap.txt +++ b/doc/argwrap.txt @@ -6,8 +6,9 @@ CONTENTS 1. ArgWrap...............................................................................................|argwrap-argwrap| 1.1. Installation...............................................................................|argwrap-installation| 1.2. Configuration.............................................................................|argwrap-configuration| - 1.3. Usage.............................................................................................|argwrap-usage| - 1.4. License.........................................................................................|argwrap-license| + 1.3. Hooks.............................................................................................|argwrap-hooks| + 1.4. Usage.............................................................................................|argwrap-usage| + 1.5. License.........................................................................................|argwrap-license| ======================================================================================================================== ARGWRAP *argwrap-argwrap* @@ -197,6 +198,66 @@ file basis using `ftplugin` or `autocmd`. For example, the `argwrap_tail_comma` ) { < +------------------------------------------------------------------------------------------------------------------------ +HOOKS *argwrap-hooks* + +It is possible to hook before or after a wrap/unwrap operation using +autoloaded functions, the hooks are named: + - `pre_wrap` + - `pre_unwrap` + - `post_wrap` + - `post_unwrap` + +For example to do something after any wrap create a function: > + argwrap#hooks#my_hook#post_wrap(range, container, arguments) +< +It is also possible to create a hook for a specific filetype: > + argwrap#hooks#filetype#vim#my_hook#post_wrap(range, container, arguments) +< + +Global hooks are loaded on the first time a wrap/unwrap operation is done. +Filetype hooks however are only loaded for the current filetype. +You can see the list of loaded hooks with: > + echo g:argwrap_global_hooks + echo g:argwrap_filetype_hooks + echo b:argwrap_hooks +< +The hooks are loaded from any directory specified in the |runtimepath|. +Global hooks will be executed before filetype ones. +Global and filetype hooks are sorted by the |globpath()| function. Meaning you +can control the execution order of the hooks by prefixing them with a +priority. + + +An important things to know when writing a new hook is that calling an +|autoload| function which does not exist will source the file that should +contain the function every time. +So even if you do not need one of the hook, always define them all. This is a +template you can use to get started: > + function! argwrap#hooks#my_hook#pre_wrap(range, container, arguments) abort " {{{ + " Do nothing but prevent the file to be loaded more than once + " When calling an autoload function that is not define the script that + " should contain it is sourced every time the function is called + endfunction " }}} + + function! argwrap#hooks#my_hook#pre_unwrap(range, container, arguments) abort " {{{ + " Do nothing but prevent the file to be loaded more than once + " When calling an autoload function that is not define the script that + " should contain it is sourced every time the function is called + endfunction " }}} + + function! argwrap#hooks#my_hook#post_wrap(range, container, arguments) abort " {{{ + " Do nothing but prevent the file to be loaded more than once + " When calling an autoload function that is not define the script that + " should contain it is sourced every time the function is called + endfunction " }}} + + function! argwrap#hooks#my_hook#post_unwrap(range, container, arguments) abort " {{{ + " Do nothing but prevent the file to be loaded more than once + " When calling an autoload function that is not define the script that + " should contain it is sourced every time the function is called + endfunction " }}} +< ------------------------------------------------------------------------------------------------------------------------ USAGE *argwrap-usage* @@ -224,3 +285,4 @@ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + vim:tw=78:sw=4:ft=help:norl: diff --git a/plugin/argwrap.vim b/plugin/argwrap.vim index 594cf67..41ce181 100644 --- a/plugin/argwrap.vim +++ b/plugin/argwrap.vim @@ -17,6 +17,7 @@ " IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN " CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +let g:argwrap_filetype_hooks = {} command! ArgWrap call argwrap#toggle()