sent 19:25:55 31 January 2011, Monday
by sgp:
> 1/ yaw (yank a word) yanks the space before the word (some times it
> doesn't); I don't want the space.
Possible suggestions here:
1. use «let @"=expand("<cword>")» (@" is a register variable, expand("<cword>") 
will expand to the word under the cursor (mnemonic: *c*urrent *word*)).
2. Use «normal! yiw», it won't take a space.
3. Do «let @"=substitute(@", '^\s\+', '', '')» thus removing preceding spaces.
> 2/ bSelection is needed to tell a function that it was invoked from visual
> mode; is there a better way?
If you want to use «normal!», then no. You may use «mode()» function for <expr> 
mappings, but mapping expressions are executed inside a textlock with additional 
restrictions including inability to use normal. Changing registers is still 
allowed, but yanking a selection without «normal!» requires much more work, for 
example see my getvrange function:
    "{{{3 map.getvrange
    function s:F.map.getvrange(start, end)
        let [sline, scol]=a:start
        let [eline, ecol]=a:end
        let text=[]
        let ellcol=col([eline, '$'])
        let slinestr=getline(sline)
        if sline==eline
            if ecol>=ellcol
                call extend(text, [slinestr[(scol-1):], ""])
            else
                call add(text, slinestr[(scol-1):(ecol-1)])
            endif
        else
            call add(text, slinestr[(scol-1):])
            let elinestr=getline(eline)
            if (eline-sline)>1
                call extend(text, getline(sline+1, eline-1))
            endif
            if ecol<ellcol
                call add(text, elinestr[:(ecol-1)])
            else
                call extend(text, [elinestr, ""])
            endif
        endif
        return text
    endfunction
It does not put anything into a register (because it was written in order to 
obtain text in a given range without modifying selection, marks and registers). 
It is able to obtain only characterwise range, for linewise range it will much 
simpler, for blockwise range it is more complex if you want to handle 
virtualedit (otherwise it is simpler). Note that I do not know a way to set a 
register that includes NULL, though vim somehow preserves NULLs when using yank 
commands. This function also preserves NULLs: it returns a list of strings where 
NL in each string really means NULL (it is a common format for 
readfile/writefile and getline/setline/append functions). Note that ecol must 
point to last byte of last character, if it points to first byte (it will when 
you use getpos), use
    let lchar=len(matchstr(getline(eline), '\%'.ecol.'c.'))
    if lchar>1
        let ecol+=lchar-1
    endif
This function maybe does not worth time spent on it, but it was a good trial.
Original message:
> What is the proper way to yank a word or a selection from a vim script?
> Right now I'm using if !bSelection
> 		normal! yaw
> 	else
> 		normal! gvy
> 	endif
> 
> but I have some gripes:
> 
> 1/ yaw (yank a word) yanks the space before the word (some times it
> doesn't); I don't want the space. 2/ bSelection is needed to tell a
> function that it was invoked from visual mode; is there a better way?
> 
> TIA
 
No comments:
Post a Comment