Vim Tips Wiki
m (Copy Cpp function declaration into implementation file moved to Copy C++ function declaration into implementation file: Replace 'Cpp' with 'C++' (originally not possible))
(minor tweaks)
(6 intermediate revisions by 2 users not shown)
Line 4: Line 4:
 
|previous=334
 
|previous=334
 
|next=336
 
|next=336
|created=October 1, 2002
+
|created=2002
 
|complexity=basic
 
|complexity=basic
 
|author=Leif Wickland
 
|author=Leif Wickland
|version=5.7
+
|version=6.0
 
|rating=22/16
 
|rating=22/16
  +
|category1=Automated Text Insertion
  +
|category2=C++
 
}}
 
}}
There's a handy plugin for MS Visual Studio called CodeWiz that has a nifty ability to copy a function declaration and deposit it into the implementation file on command. I actually missed while using vim, so I wrote an approximation of that capability. This isn't foolproof, but it works alright.
+
There is a plugin for Microsoft Visual Studio called CodeWiz. It can copy a function declaration in a header, then automatically paste the implementation skeleton in the source file.
   
  +
There are multiple ways to grant similar functionality in Vim.
<pre>
 
" Copy Function Declaration from a header file into the implementation file.
 
nmap &lt;F5&gt; "lYml<nowiki>[[</nowiki>kw"cye'l
 
nmap &lt;F6&gt; ma:let @n=@/&lt;cr&gt;"lp==:s/\&lt;virtual\&gt;/\/\*&amp;\*\//e&lt;cr&gt;:s/\&lt;static\&gt;/\/\*&amp;\*\//e&lt;cr&gt;:s/\s*=\s*0\s*//e&lt;cr&gt;:s/(.\{-}\zs=\s*[^,)]\{-1,}\&gt;\ze\(\*\/\)\@!.*)/\/\*&amp;\*\//e&lt;cr&gt;:s/(.\{-}\zs=\s*[^,)]\{-1,}\&gt;\ze\(\*\/\)\@!.*)/\/\*&amp;\*\//e&lt;cr&gt;:s/(.\{-}\zs=\s*[^,)]\{-1,}\&gt;\ze\(\*\/\)\@!.*)/\/\*&amp;\*\//e&lt;cr&gt;:let @/=@n&lt;cr&gt;'ajf(b"cPa::&lt;esc&gt;f;s&lt;cr&gt;{&lt;cr&gt;}&lt;cr&gt;&lt;esc&gt;kk
 
</pre>
 
   
  +
==Simple method==
To use this, source it into vim, for example by placing it in your vimrc, press F5 in normal mode with the cursor on the line in the header file that declares the function you wish to copy. Then go to your implementation file and hit F6 in normal mode with the cursor where you want the function implementation inserted.
 
  +
<source lang="vim">
  +
" Copy function declaration from a header file into the implementation file.
  +
nmap <F5> "lYml<nowiki>[[</nowiki>kw"cye'l
  +
nmap <F6> ma:let @n=@/<CR>"lp==:s/\<virtual\>/\/\*&\*\//e<CR>:s/\<static\>/\/\*&\*\//e<CR>:s/\s*=\s*0\s*//e<CR>:s/(.\{-}\zs=\s*[^,)]\{-1,}\>\ze\(\*\/\)\@!.*)/\/\*&\*\//e<CR>:s/(.\{-}\zs=\s*[^,)]\{-1,}\>\ze\(\*\/\)\@!.*)/\/\*&\*\//e<CR>:s/(.\{-}\zs=\s*[^,)]\{-1,}\>\ze\(\*\/\)\@!.*)/\/\*&\*\//e<CR>:let @/=@n<CR>'ajf(b"cPa::<Esc>f;s<CR>{<CR>}<CR><Esc>kk
  +
</source>
   
  +
To use this, source it into Vim, for example by placing it in your [[vimrc]]. Then, press F5 (in normal mode) with the cursor on the line in the header file that declares the function you wish to copy. Then go to your source file and hit F6 (in normal mode) with the cursor where you want to insert the function implementation.
==Comments==
 
I liked the idea behind Leif's tip and I thought ''a'' command you could call in the header ''or'' source file would be good (one less thing for me to remember) an besides I knew just how I wanted to do it! Along the way I've made a slight improvement or two (no longer clobbers registers/marks for instance). This is formatted to stuff into a file and drop into your plugin directory.
 
   
  +
==Method with namespaces==
So it seems to work in most cases (single line Member functions all(?) seem to work, anything else well, doesn't) (trips on the same things Leif's implementation does of course because it IS Leif's implementation! I just moved some lines around ;) )
 
  +
The above tip does not support namespaces. The script below builds upon the above idea to implement namespace support, along with more portable and reliable ways of determining the class and namespace name.
  +
<source lang="vim">
  +
nmap <F5> :CopyDefinition<CR>
  +
nmap <F6> :ImplementDefinition<CR>
  +
command! CopyDefinition :call s:GetDefinitionInfo()
  +
command! ImplementDefinition :call s:ImplementDefinition()
  +
function! s:GetDefinitionInfo()
  +
exe 'normal ma'
  +
" Get class
  +
call search('^\s*\<class\>', 'b')
  +
exe 'normal ^w"ayw'
  +
let s:class = @a
  +
let l:ns = search('^\s*\<namespace\>', 'b')
  +
" Get namespace
  +
if l:ns != 0
  +
exe 'normal ^w"ayw'
  +
let s:namespace = @a
  +
else
  +
let s:namespace = ''
  +
endif
  +
" Go back to definition
  +
exe 'normal `a'
  +
exe 'normal "aY'
  +
let s:defline = substitute(@a, ';\n', '', '')
  +
endfunction
   
  +
function! s:ImplementDefinition()
<pre>
 
  +
call append('.', s:defline)
" vim:ff=unix ts=4 ss=4
 
  +
exe 'normal j'
" vim60:fdm=marker
 
  +
" Remove keywords
" \file copycppdectoimp.vim
 
  +
s/\<virtual\>\s*//e
"
 
  +
s/\<static\>\s*//e
" \brief From Vim-Tip #335: Copy C++ function declaration into implementation file
 
  +
if s:namespace == ''
" by Leif Wickland as of Vim: 5.7
 
  +
let l:classString = s:class . "::"
" \note See: http://vim.sourceforge.net/tip_view.php?tip_id=335
 
  +
else
"
 
  +
let l:classString = s:namespace . "::" . s:class . "::"
" \author Leif Wickland
 
  +
endif
" \author (Mangled by) Robert KellyIV &lt;Feral&gt;
 
  +
" Remove default parameters
" \note This file and work is based totally on Leif Wickland's Vim-TIP#335
 
  +
s/\s\{-}=\s\{-}[^,)]\{1,}//e
" \date Tue, 01 Oct 2002 21:03 Pacific Daylight Time
 
  +
" Add class qualifier
" \version $Id$
 
  +
exe 'normal ^f(bi' . l:classString
" Version: 0.2
 
  +
" Add brackets
" History: {{{
 
  +
exe "normal $o{\<CR>\<TAB>\<CR>}\<CR>\<ESC>kkkk"
" [Feral:274/02@20:42] 0.2
 
  +
" Fix indentation
" Improvments: from Leif's Tip (#335):
 
  +
exe 'normal =4j^'
" * can handle any number of default prams (as long as they are all
 
  +
endfunction
" on the same line!)
 
  +
</source>
" * Options on how to format default params, virtual and static.
 
" (see below) TextLink:||@|Prototype:|
 
" * placed commands into a function (at least I think it's an
 
" improvement ;) )
 
" * Improved clarity of the code, at least I hope.
 
" * Preserves registers/marks. (rather does not use marks), Should
 
" not dirty anything.
 
" * All normal operations do not use mappings i.e. :normal!
 
" (I have Y mapped to y$ so Leif's mappings could fail.)
 
"
 
" Limitations:
 
" * fails on multi line declorations. All prams must be on the same
 
" line.
 
" * fails for non member functions. (though not horibly, just have
 
" to remove the IncorectClass:: text...
 
" 0.1
 
" Leif's original Vim-Tip #335
 
" }}}
 
   
  +
It is recommended that you copy this into a .vim file, and place it in your plugins directory as opposed to pasting it directly in your .vimrc file.
if exists("loaded_copycppdectoimp")
 
finish
 
endif
 
let loaded_copycppdectoimp = 1
 
   
  +
The script is used similar to the one above. Press F5 (in normal mode) with the cursor on the line in the header file that declares the function you wish to copy. Then, go to your source file and hit F6 (in normal mode) with the cursor where you want to insert the function implementation.
"{{{ [basic] Tip #335: Copy C++ function declaration into implementation file
 
" tip karma Rating 5/2, Viewed by 49
 
"
 
"created: October 1, 2002 6:47 complexity: basic
 
"author: Leif Wickland as of Vim: 5.7
 
"
 
"There's a handy plugin for MS Visual Studio called CodeWiz that has a nifty ability to copy a function declaration and deposit it into the implementation file on command. I actually missed while using vim, so I wrote an approximation of that capability. This isn't foolproof, but it works alright.
 
"
 
"" Copy Function Declaration from a header file into the implementation file.
 
"nmap &lt;F5&gt; "lYml<nowiki>[[</nowiki>kw"cye'l
 
"nmap &lt;F6&gt; ma:let @n=@/&lt;cr&gt;"lp==:s/\&lt;virtual\&gt;/\/\*&amp;\*\//e&lt;cr&gt;:s/\&lt;static\&gt;/\/\*&amp;\*\//e&lt;cr&gt;:s/\s*=\s*0\s*//e&lt;cr&gt;:s/(.\{-}\zs=\s*[^,)]\{-1,}\&gt;\ze\(\*\/\)\@!.*)/\/\*&amp;\*\//e&lt;cr&gt;:s/(.\{-}\zs=\s*[^,)]\{-1,}\&gt;\ze\(\*\/\)\@!.*)/\/\*&amp;\*\//e&lt;cr&gt;:s/(.\{-}\zs=\s*[^,)]\{-1,}\&gt;\ze\(\*\/\)\@!.*)/\/\*&amp;\*\//e&lt;cr&gt;:let @/=@n&lt;cr&gt;'ajf(b"cPa::&lt;esc&gt;f;s&lt;cr&gt;{&lt;cr&gt;}&lt;cr&gt;&lt;esc&gt;kk
 
"
 
"To use this, source it into vim, for example by placing it in your vimrc, press F5 in normal mode with the cursor on the line in the header file that declares the function you wish to copy. Then go to your implementation file and hit F6 in normal mode with the cursor where you want the function implementation inserted.
 
" }}}
 
   
  +
==Comments==
function! &lt;SID&gt;GrabFromHeaderPasteInSource(howtoshowVirtual, howtoshowStatic, howtoshowDefaultParams) "{{{
 
  +
The tip seems to work in most cases (single line Member functions all(?) seem to work, anything else well, doesn't).
" echo confirm(expand("%:e"))
 
if expand("%:e") ==? "h"
 
 
"nmap &lt;F5&gt; "lYml<nowiki>[[</nowiki>kw"cye'l
 
" execute ":normal! ml"
 
let SaveL = line(".")
 
let SaveC = virtcol(".")
 
 
" into l yank the entire line
 
" ([Feral:274/02@19:06] MY Y is mapped to y$, so I account for that below)
 
:let Was_Reg_l = @l
 
" execute ':normal! "lY'
 
execute ':normal! 0"ly$'
 
" echo confirm(@l)
 
:let s:LineWithDecloration = @l
 
:let @l=Was_Reg_l
 
 
" [Feral:274/02@14:41] this works peachy for a member function, not so
 
" well for a normal function, how can we fix this? Or do we bother?
 
execute ":normal! <nowiki>[[</nowiki>"
 
execute ":normal! kw"
 
:let Was_Reg_c = @c
 
execute ':normal! "cye'
 
:let s:ClassName = @c
 
:let @c=Was_Reg_c
 
 
" execute ":normal! 'l"
 
:execute ":normal! ".SaveL."G"
 
:execute ":normal! ".SaveC."|"
 
 
" echo confirm(s:ClassName)
 
else
 
" echo confirm(s:ClassName)
 
let SaveL = line(".")
 
let SaveC = virtcol(".")
 
" :execute ':normal! ma'
 
:let Was_Reg_n = @n
 
:let @n=@/
 
:execute ':normal! O'.s:LineWithDecloration
 
:execute ':normal! =='
 
 
" XXX if you want virtual commented in the implimentation:
 
if a:howtoshowVirtual == 1
 
:s/\&lt;virtual\&gt;/\/\*&amp;\*\//e
 
else
 
" XXX else, remove virtual and any spaces/tabs after it.
 
:s/\&lt;virtual\&gt;\s*//e
 
endif
 
 
" XXX if you want static commented in the implimentation:
 
if a:howtoshowStatic == 1
 
:s/\&lt;static\&gt;/\/\*&amp;\*\//e
 
else
 
" XXX else, remove static and any spaces/tabs after it.
 
:s/\&lt;static\&gt;\s*//e
 
endif
 
 
" wipe out a pure virtual thingie-ma-bob. (technical term? (= )
 
:s/\s*=\s*0\s*//e
 
 
" Handle default params, if any.
 
if a:howtoshowDefaultParams == 1
 
" Remove the default param assignments.
 
:s/\s\{-}=\s\{-}[^,)]\{1,}//ge
 
else
 
" Comment the default param assignments.
 
:s/\s\{-}\(=\s\{-}[^,)]\{1,}\)/\/\*\1\*\//ge
 
 
if a:howtoshowDefaultParams == 3
 
" Remove the = and any spaces to the left or right.
 
:s/\s*=\s*//ge
 
endif
 
endif
 
 
:let @/=@n
 
:let @n=Was_Reg_n
 
:execute ":normal! ".SaveL."G"
 
:execute ":normal! ".SaveC."|"
 
:execute ':normal! f(b'
 
:execute ':normal! i'.s:ClassName.'::'
 
 
" find the ending ; and replace it with a brace structure on the next line.
 
:execute ":normal! f;s\&lt;cr&gt;{\&lt;cr&gt;}\&lt;cr&gt;\&lt;esc&gt;kk"
 
endif
 
endfunc
 
"}}}
 
 
" given:
 
" virtual void Test_Member_Function_B3(int _iSomeNum2 = 5, char * _cpStr = "Yea buddy!");
 
 
" Prototype:
 
"GrabFromHeaderPasteInSource(VirtualFlag, StaticFlag, DefaultParamsFlag)
 
 
" VirtualFlag:
 
" 1: if you want virtual commented in the implimentation:
 
" /*virtual*/ void Test_Member_Function_B3(int _iSomeNum2 = 5, char * _cpStr = "Yea buddy!");
 
" else: remove virtual and any spaces/tabs after it.
 
" void Test_Member_Function_B3(int _iSomeNum2 = 5, char * _cpStr = "Yea buddy!");
 
 
" StaticFlag:
 
" 1: if you want static commented in the implementation:
 
" Same as virtual, save deal with static
 
" else: remove static and any spaces/tabs after it.
 
" Same as virtual, save deal with static
 
 
" DefaultParamsFlag:
 
" 1: If you want to remove default param reminders, i.e.
 
" Test_Member_Function_B3(int _iSomeNum2, char * _cpStr);
 
" 2: If you want to comment default param assignments, i.e.
 
" Test_Member_Function_B3(int _iSomeNum2/*= 5*/, char * _cpStr/*= "Yea buddy!"*/);
 
" 3: Like 2 but, If you do not want the = in the comment, i.e.
 
" Test_Member_Function_B3(int _iSomeNum2/*5*/, char * _cpStr/*"Yea buddy!"*/);
 
"
 
" Examples:
 
" smallest implimentation:
 
" void Test_Member_Function_B3(int _iSomeNum2, char * _cpStr);
 
":command! -nargs=0 GHPH call &lt;SID&gt;GrabFromHeaderPasteInSource(0,0,1)
 
" Verbose...:
 
" /*virtual*/ void Test_Member_Function_B3(int _iSomeNum2/*5*/, char * _cpStr/*"Yea buddy!"*/);
 
":command! -nargs=0 GHPH call &lt;SID&gt;GrabFromHeaderPasteInSource(1,1,3)
 
" What I like:
 
" void Test_Member_Function_B3(int _iSomeNum2/*5*/, char * _cpStr/*"Yea buddy!"*/);
 
:command! -nargs=0 GHPH call &lt;SID&gt;GrabFromHeaderPasteInSource(0,0,3)
 
</pre>
 
   
 
Several things can still be improved:
 
Several things can still be improved:
* There is no need for using registers
+
*There is no need for using registers.
* We can easily find the class name (if any) -- ''easy'' because I'd already done this for my set of C++ ftplugins
+
*We can easily find the class name (if any) -- ''easy'' because I'd already done this for my set of C++ ftplugins.
* We can accept prototypes written on several lines (this first version only supports parameters written on several lines).
+
*We can accept prototypes written on several lines (this first version only supports parameters written on several lines).
   
 
There are still some other things that can be done to improve this '''ft'''plugin, but here is a first (third) shot.
 
There are still some other things that can be done to improve this '''ft'''plugin, but here is a first (third) shot.
   
  +
The resulting script is now part of my {{script|id=336|text=C&C++ ftplugins suite}}.
<pre>[..snip code..]</pre>
 
--[[User:Luc Hermitte|Luc Hermitte]], October 7, 2002 15:36
 
:The resulting script is now part of my {{script|id=336|text=C&amp;C++ ftplugins suite}}.
 
 
:--[[User:Luc Hermitte|Luc Hermitte]] 13:04, 24 July 2007 (UTC)
 
:--[[User:Luc Hermitte|Luc Hermitte]] 13:04, 24 July 2007 (UTC)
----
 
[[Category:Automated Text Insertion]]
 
[[Category:C++]]
 

Revision as of 08:15, 19 April 2011

Tip 335 Printable Monobook Previous Next

created 2002 · complexity basic · author Leif Wickland · version 6.0


There is a plugin for Microsoft Visual Studio called CodeWiz. It can copy a function declaration in a header, then automatically paste the implementation skeleton in the source file.

There are multiple ways to grant similar functionality in Vim.

Simple method

" Copy function declaration from a header file into the implementation file.
nmap <F5> "lYml<nowiki>[[</nowiki>kw"cye'l
nmap <F6> ma:let @n=@/<CR>"lp==:s/\<virtual\>/\/\*&\*\//e<CR>:s/\<static\>/\/\*&\*\//e<CR>:s/\s*=\s*0\s*//e<CR>:s/(.\{-}\zs=\s*[^,)]\{-1,}\>\ze\(\*\/\)\@!.*)/\/\*&\*\//e<CR>:s/(.\{-}\zs=\s*[^,)]\{-1,}\>\ze\(\*\/\)\@!.*)/\/\*&\*\//e<CR>:s/(.\{-}\zs=\s*[^,)]\{-1,}\>\ze\(\*\/\)\@!.*)/\/\*&\*\//e<CR>:let @/=@n<CR>'ajf(b"cPa::<Esc>f;s<CR>{<CR>}<CR><Esc>kk

To use this, source it into Vim, for example by placing it in your vimrc. Then, press F5 (in normal mode) with the cursor on the line in the header file that declares the function you wish to copy. Then go to your source file and hit F6 (in normal mode) with the cursor where you want to insert the function implementation.

Method with namespaces

The above tip does not support namespaces. The script below builds upon the above idea to implement namespace support, along with more portable and reliable ways of determining the class and namespace name.

nmap <F5> :CopyDefinition<CR>
nmap <F6> :ImplementDefinition<CR>
command! CopyDefinition :call s:GetDefinitionInfo()
command! ImplementDefinition :call s:ImplementDefinition()
function! s:GetDefinitionInfo()
  exe 'normal ma'
  " Get class
  call search('^\s*\<class\>', 'b')
  exe 'normal ^w"ayw'
  let s:class = @a
  let l:ns = search('^\s*\<namespace\>', 'b')
  " Get namespace
  if l:ns != 0
    exe 'normal ^w"ayw'
    let s:namespace = @a
  else
    let s:namespace = ''
  endif
  " Go back to definition
  exe 'normal `a'
  exe 'normal "aY'
  let s:defline = substitute(@a, ';\n', '', '')
endfunction

function! s:ImplementDefinition()
  call append('.', s:defline)
  exe 'normal j'
  " Remove keywords
  s/\<virtual\>\s*//e
  s/\<static\>\s*//e
  if s:namespace == ''
    let l:classString = s:class . "::"
  else
    let l:classString = s:namespace . "::" . s:class . "::"
  endif
  " Remove default parameters
  s/\s\{-}=\s\{-}[^,)]\{1,}//e
  " Add class qualifier
  exe 'normal ^f(bi' . l:classString
  " Add brackets
  exe "normal $o{\<CR>\<TAB>\<CR>}\<CR>\<ESC>kkkk"
  " Fix indentation
  exe 'normal =4j^'
endfunction

It is recommended that you copy this into a .vim file, and place it in your plugins directory as opposed to pasting it directly in your .vimrc file.

The script is used similar to the one above. Press F5 (in normal mode) with the cursor on the line in the header file that declares the function you wish to copy. Then, go to your source file and hit F6 (in normal mode) with the cursor where you want to insert the function implementation.

Comments

The tip seems to work in most cases (single line Member functions all(?) seem to work, anything else well, doesn't).

Several things can still be improved:

  • There is no need for using registers.
  • We can easily find the class name (if any) -- easy because I'd already done this for my set of C++ ftplugins.
  • We can accept prototypes written on several lines (this first version only supports parameters written on several lines).

There are still some other things that can be done to improve this ftplugin, but here is a first (third) shot.

The resulting script is now part of my C&C++ ftplugins suite.

--Luc Hermitte 13:04, 24 July 2007 (UTC)