2

I'm trying to write a little function that will help when I'm debugging code with Stata. All I want is for vim to count up the number of times a line begins with di "here and then insert di "here XX" into the current line in the buffer, where XX is the number of times.

This is what I have:

fun! ADD_Here()
    let n=[0] | bufdo %s/^di\ \"here\zs/\=map(n,'v:val+1')[1:]/ge
    put='di \"here ' . n[0] . '\"'
endfun
nmap <leader>d :<C-U>call ADD_Here()<CR>

This works almost exactly as intended, it does all the counting and inserts text, but it always puts the second insert right below the first one, and then the third below the second, etc. How do I modify this so it inserts at the current line?

For citation purposes, I got the code for the let n=[0]... statement here.

Community
  • 1
  • 1

2 Answers2

2

:[line]put always puts text below line [line] or the current line if there is no [line].

Use call setline('.', 'di \"here ' . n[0] . '\"') to change the current line.

romainl
  • 186,200
  • 21
  • 280
  • 313
  • I'm not sure what you mean by use `setline()`. Putting that statement after `put=` inserts a 0 after inserting `di "here 0"` and then continues inserting a 0 after that first 0 every time after. Using it by itself or before the `put` command makes a bunch of errors. – Brian Albert Monroe Feb 27 '15 at 21:51
  • It is a function so it must be `:call`ed *instead* of `put=…`. See my edit. – romainl Feb 27 '15 at 22:09
  • using `call setline('.', 'di \"here ' . n[0] . '\"')` inserts at the current line, then increments the number on the same line by 1 once instead of inserting a new line, and then doesn't increment thereafter. – Brian Albert Monroe Feb 27 '15 at 22:15
0

The issue is resolved by storing the current line number before the counting happens, moving to that line after the counting, using the setline function to insert text with a unique keyword (thanks @romani for bringing this function to my attention), and then replacing that keyword with the count stored in n[0]. I also added the exec 'normal O' command before the setline function to insert a newline above the current line so that the current line isn't replaced by the debugging text.

    fun! ADD_Here()
        "Store the current line number in a variable
        let cline = line('.') 

        "Store the count of lines beginning with 'di "here' in a list
        let n=[0] | bufdo %s/^di\ \"here\zs/\=map(n,'v:val+1')[1:]/ge     

        "The above command moves the current line if n[0]>0, so go back to the saved value
        exec cline

        "Create a blank line above the current line and move to it
        exec 'normal O'

        "Insert text with a unique keyword '__stata_debug__' on the current line
        call setline('.','di "here __stata_debug__"')

        "Replace the unique keyword with the count of lines beginning with 'di "here'
        exec '%s/__stata_debug__/'.n[0].'/g'
    endfun
    "Map to function to <leader>d
    nmap <leader>d :<C-U>call ADD_Here()<CR>