0

I have a file, say:

Program  foo
Implicit None
integer::ab
End Program bar

Now, I want the "bar" in last line to be "foo" (i.e. Program and End program name should be same). I wrote a python script for this, which works very well:

#!/usr/bin/python
import fileinput
with open("i.f90") as inp:
    for line in inp:
        if line.startswith("Program"):
            var = line.rsplit(' ', 1)[-1].strip()
        if line.startswith("End Program"):
            v2 = line.strip()
            print v2
inp.close()
STR="End Program "+var
print STR
for line in fileinput.input("i.f90", inplace=True):
    print line.replace(v2, STR).strip()

But, as I want to call it from vim, as a ftplugin, I put it in vim's ftplugin as:

function! Edname() 
python<<EOF
import vim
import fileinput
with open("i.f90") as inp:
    for line in inp:
        if line.startswith("Program"):
            var = line.rsplit(' ', 1)[-1].strip()
        if line.startswith("End Program"):
            v2 = line.strip()
            print v2
inp.close()
STR="End Program "+var
print STR
for line in fileinput.input("i.f90", inplace=True):
    print line.replace(v2, STR).strip()
EOF
endfunction

As you can see the only changes I have made is to put it in vim. No real change in the actual python code. But in this case, this is not working. It is printing the v2 and STR properly, but the line in the file (or the buffer) is not getting updated.

Any clue?

This is largely to do with my earlier post. But now, I have find a partial solution with python, but that is not working when called from vim.

1 Answer 1

2

If that's what you mean by automation, you don't need Python. Just put something like this in a ftplugin for your filetype:

function! s:FixName()
    let [buf, l, c, off] = getpos('.')
    call cursor([1, 1, 0])

    let lnum = search('\v\c^Program\s+', 'cnW')
    if !lnum
        call cursor(l, c, off)
        return
    endif

    let parts = matchlist(getline(lnum), '\v\c^Program\s+(\S*)\s*$')
    if len(parts) < 2
        call cursor(l, c, off)
        return
    endif

    let lnum = search('\v\c^End\s+Program\s+', 'cnW')
    call cursor(l, c, off)
    if !lnum
        return
    endif

    call setline(lnum, substitute(getline(lnum), '\v\c^End\s+Program\s+\zs.*', parts[1], ''))
endfunction

call s:FixName()

You can also do it with a macro, but that doesn't look as clever as the function above. ;) Something like this:

nnoremap <buffer> <silent> <C-p> /\v\c^Program\s+\zs<CR>"zy$/\v\c^End\s+Program\s+\zs<CR>D"zP
Sign up to request clarification or add additional context in comments.

5 Comments

I tried that (a blind copy; cant claim I have understood that), but :call s:FixName() gives me error: E41: Using <SID> not in a script context
@BaRud As I said: "put [it] in a ftplugin for your filetype" (the ftplugin will call the function when you first open your file). Or write it to a file foo.vim and source it from the current file: :so foo.vim. Or drop the s: from the function name if you absolutely must call it manually.
Thanks...its working perfectly now. But, as I said, I hardly understood it, can I use an arg in it, and, say, work as: lnum = search('\v\c^a:arg\s+', 'cnW')? I tried, but this is not working
@BaRud The script addresses your question the way you asked it. If you want to modify it, I believe you're supposed to ask a new question. However, I'd say a better way for you would be to start with macro at the end of my post and understand that. It doesn't do anything tricky, really.
when time permits, may you kindly have a look at stackoverflow.com/questions/31022184/… This is the new question as you asked.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.