I'm trying to write a function in my vimrc that would allow me to "hover" the in vim cursor (not the mouse cursor) over the word in question and and create a doc comment (with the word already in the comment) along with the new subroutine. So I would start with just:
newSubName
and then hover over and call the sub, it would replace that with:
#------------------------------------------------------------------------------
# Subroutine: newSubName
# Function :
# Parms :
# Returns :
# Assumes :
#------------------------------------------------------------------------------
sub newSubName() {
}
I have the code for creating the sub "declaration" at the bottom of the file (got from internet), but I can't really decipher how to turn it into what I want. The code that I am using is:
function! Newsub()
let word = "sub " . expand("<cword>") . "()" . " {" . "}"
let ln = search("__.*__", 'nW')
if ln == 0
call append('$', word)
else
call append(ln-1, word)
endif
endfunction
Any and all help is appreciated.
Thanks,
RzITex
Any templates/snippets expander should simplify your life. For instance, with mu-template v2.4.0 (only available through svn/vim-addon-manager for the moment):
VimL: " {rtp}/after/template/{filetype}/func.template
#------------------------------------------------------------------------------
# Subroutine: <+g:func+>
# Function : <++>
# Parms : <++>
# Returns : <++>
# Assumes : <++>
# Date : <+strftime('%c')+>
# Author : <+g:myname_that_I_need_to_define_in_my_vimrc+>
#------------------------------------------------------------------------------
sub <+g:func+>() {
<++>
}<++>
and the ftplugin {rtp}/ftplugin/{filetype}.vim
" here the anti-inclusion guards, ...
" and the untested mapping
nnoremap <buffer> <c-x>f :let g:func=expand('<cword>')<cr>"_diw:exe "Mutemplate ".&ft."/func"<cr>:unlet g:func<cr>
Note: this mapping contain everything that you need:
obtain the current word (there are many other methods)
delete that word with "_diw (:h "_, :h diw)
apply something that will do the expansion. If you prefer to work manually with a function that calls :put, name it s:FuncExpand(name) for instance, and call it from the mapping with diw:call <sid>FuncExpand(#")<cr> (here I use another way to cut the function name under the cursor).
Related
I know how to comment out multiple lines in VIM, but what if I wanted to add comments in the end of each line?
For example:
function dir.ls(path)
local i,files = 0,{}
local pfile = io.popen('ls "'..path..'"')
for fname in pfile:lines() do
i = i + 1
fpath = path..fname
files[i] = fpath
end
pfile:close()
return files
end
Now with added comments:
function dir.ls(path)
local i,files = 0,{}
local pfile = io.popen('ls "'..path..'"')
for fname in pfile:lines() do
i = i + 1
fpath = path..fname -- your comment goes here
files[i] = fpath -- your comment goes here
end
pfile:close() -- your comment goes here
return files
end
Append your comment to the first line:
A -- your comment goes here<Esc>
Move the cursor to the next line you want to add a comment to.
Repeat the last edit:
.
And so on…
In your example:
A -- your comment goes here<Esc>
j.
jj.
Another method, but in a single step:
:,+3v/end/norm A -- your comment goes here<CR>
That command is easier to understand if it is explained from right to left:
The :normal command allows you to execute a sequence of normal mode commands from command-line mode. Here, we use it to append the comment to the given line, just like in the first step of the multi-step method.
v/pattern/command is a companion to the :global command. It means "run the given command on every line in the given range that doesn't match pattern". Here, we run our :normal command on every line in the given range that doesn't contain end.
,+3 is the range of lines on which we want to run the :v command. It is a shortened version of .,+3 which means "the current line and the next three lines".
I'm currently trying to write a script allowing to call a Vim command, which in turns calls an external command. I want to enable auto-completion with results within a list of files having a specific extension (see code below).
The completion actually circles through the list of files with the given extension, but when I start typing something and press tab, the completion is cycle is repeated from the start of the list, regardless of what's being entered (instead of actually completing the rest of the file name given in input). The code is the following:
call CreateEditCommand('EComponent', 'ComponentFiles')
function! CreateEditCommand(command, listFunction)
silent execute 'command! -nargs=1 -complete=customlist,'. a:listFunction . ' ' . a:command . ' call EditFile(<f-args>)'
endfunction
function! ComponentFiles(A,L,P)
return Files('component.ts')
endfunction
function! Files(extension)
let paths = split(globpath('.', '**/*.' . a:extension), "\n")
let idx = range(0, len(paths)-1)
let g:global_paths = {}
for i in idx
let g:global_paths[fnamemodify(paths[i], ':t:r')] = paths[i]
endfor
call map(paths, 'fnamemodify(v:val, ":t:r")')
return paths
endfunction
function! EditFile(file)
execute 'edit' g:global_paths[a:file]
endfunction
For instance, if I have: app.component.ts, and test.component.ts and I type
:EComponent test
and press tab, the completed command will is the following
:EComponent app.component.ts
instead of:
:EComponent test.component.ts
Thanks in advance for your help on this.
ComponentFiles() is supposed to filter the list of files based on the characters before the cursor (ArgLead) but you always return the same list so that function does nothing useful.
The custom completion function below returns only the items in ls that match the characters before the cursor:
function! MyComp(ArgLead, CmdLine, CursorPos)
return filter(systemlist("ls"), 'v:val =~ a:ArgLead')
endfunction
function! MyFunc(arg)
execute "edit " . a:arg
endfunction
command! -nargs=1 -complete=customlist,MyComp MyEdit call MyFunc(<f-args>)
See :help :command-completion-customlist.
I noticed that fold texts can show useful information. They usually show something like
+-- 5 lines: <div id="header-inner">--------------------------------------------
Is it possible to change the text in those lines? I noticed that something is possible in foldexpr but would it be possible to completely redesign folds?
e.g.
+ <div id="header-inner"> : "possible comment from line above" : row 27 : length 5
thank you
There are a few things I don't understand from your question, such as which foldmethod you are using, or what the number of "rows" refers to, but here's a custom foldtext function that should do roughly what you want:
function! MyFoldText()
let nl = v:foldend - v:foldstart + 1
let comment = substitute(getline(v:foldstart),"^ *","",1)
let linetext = substitute(getline(v:foldstart+1),"^ *","",1)
let txt = '+ ' . linetext . ' : "' . comment . '" : length ' . nl
return txt
endfunction
set foldtext=MyFoldText()
Explanation:
Find the number of lines contained by the fold.
Get the "comment" from the line before the first folded line (and remove leading spaces).
Get the text from the first line of the fold (and remove leading spaces).
Assemble the above information into the returned foldtext, with appropriate formatting.
Hope this helps. It should be easily tailored to your needs.
You can also inspect the folding config from Steve Losh’s bitbucket repo page about vim.
It has very beautiful appearance, which is also very organized!
To see what it is like, you might ckeck it out in this youtube video.
I am using ruby on rails but that does not matter much for this question. Let's say that i have a statement like this
error = 'this is an error message'
I have noticed that I end up doing this a lot
error = 'this is an error message'
puts "error = #{error.inspect}"
I am sure a macro can be written which would take the work on the left hand side of left most = and then create another line along with template shown above.
I am using mvim on mac. Any pointer in terms of where I should start to look for developing what I want.
Try snipmate:
http://www.vim.org/scripts/script.php?script_id=2540
I recorded a simple macro that does your sample. To record a macro type q followed by what register you want the macro to be put in (convention calls for qq). To play the macro type # then the macro register. You can view this at :help recording
To write the macro, use the following commands (and here is how is should look in the register)
^yEoputs "error = #{^Op.inspect}"^[
^ moves to the first non whitespace character of the line
yE yanks to the end of the space separated word.
o Puts you in insert mode on the next line
puts "error = #{ is the text that you type out
^O is ctrl+O (capital letter o) - this allows the next, and only the next command to be run in command mode, which is...
p Puts the yanked word, after this command is run you're still in insert mode
.inspect}" is the text that you type and finally...
^[ is Esc
I would go for:
nnoremap µ :s/^\s*\(\k\+\)\s*=.*/&\rputs "\1 = #{\1.inspect}"/<cr>
:s presents the advantage of doing the job plus matching the assigned variable if any. Doing the same thing with classical commands like yw, p, etc would be more cumbersome.
If the template become more complex, we can rely on template-file expanders as long as they easily permit to call viml function like matchstr(). Of course, in that case I would use mu-template with the following template-file:
VimL:" $Id: {rtp}/template/ruby/inspect.template
VimL: let s:value_start = '¡'
VimL: let s:value_end = '¡'
VimL: let s:reindent = 1
VimL: let s:marker_open = '<+'
VimL: let s:marker_close = '+>'
VimL: let s:varname = matchstr(getline(line('.')-1), '^\s*\zs\k\+\ze\s*=')
VimL: if empty(s:varname) |throw "the previous line don't assign any variable" |endif
puts "¡s:varname¡ = #{¡s:varname¡.inspect}"<++>
VimL:"vim: encoding=utf-8
If you're doing these on the fly, a snipmate snippet could look like this:
${1:error} = '${2:error message here}'
puts "error = #{$1.inspect}"
If, on the other hand you're just wanting to output pre-existing variables for debugging purposes. Nick-Canzoneri's macro may be more useful.
I want to use vim to write a part of my file to another file. For example, I have the following file:
This is line 1
and this is the next line
I want my output file to read:
line 1
and this is
I know how to use vi to write a range of lines to a file:
:20,22 w partial.txt
An alternative is to visually select the desired text and then write:
:'<'> w partial.txt
However, when using this method, vim insists on writing the full line in the output, and I have found no way to write a partial line. Any thoughts?
I've got two (very similar) approaches to this. There's no way to do it with the built in write command, but it's fairly easy to generate your own function that should do what you want (and you can call it what you like - even W if you want).
A very simple approach that will only handle single-line ranges is to have a function like this:
command! -nargs=1 -complete=file -range WriteLinePart <line1>,<line2>call WriteLinePart(<f-args>)
function! WriteLinePart(filename) range
" Get the start and end of the ranges
let RangeStart = getpos("'<")
let RangeEnd = getpos("'>")
" Result is [bufnum, lnum, col, off]
" Check both the start and end are on the same line
if RangeStart[1] == RangeEnd[1]
" Get the whole line
let WholeLine = getline(RangeStart[1])
" Extract the relevant part and put it in a list
let PartLine = [WholeLine[RangeStart[2]-1:RangeEnd[2]-1]]
" Write to the requested file
call writefile(PartLine, a:filename)
endif
endfunction
This is called with :'<,'>WriteLinePart test.txt.
If you want to support multiple line ranges, you could either expand this to include varying conditions, or you could pinch the code from my answer to this question. Get rid of the bit about substituting backslashes and you could then have a very simple function that does something like (untested though...) this:
command! -nargs=1 -complete=file -range WriteLinePart <line1>,<line2>call writelines([GetVisualRange()], a:filename)