0

I'm trying to write some script (a function) which I can use to add some additions to a BASH script I'm modifying. This BASH script automates the building of a series of packages. The part of the script I'm wanting to modify is to add an "or die" clause after the three points for which I want some additional info. Consider this

die() {
    [[ -z $1 ]] && msg="Unintended early exit" || msg=$1
    echo $msg
    exit 1
}
...

# This is the basic pattern
echo "package"
cd package
mkdir build && cd build
../configure <options>
make -j 8
make install
cd $TOP

I want to add onto the configure, build and install lines with the die() function to help in seeing when problems are encountered:

# This is the basic pattern
echo "package"
cd package
mkdir build && cd build
../configure <options> || die "package failed to configure"
make -j 8 || die "package failed to build"
make install || die "package failed to install"
cd $TOP

Since each "block" of the script starts with the echo command, I'm basically wanting to do this g/^echo/call AddDie().

So, I'm trying to write a function named AddDie() which basically does

  • copy package into the 0 register
  • "for this block" append: die || "ph failed to ..."
  • "for this block" change each instance of "ph" to "package"

For this I've tried various things like this

function! AddDie()
    exec 'norm f"lyt"'
    exec 'norm }me``'
    .,'eg/configure/exec 'norm A || die "ph failed to configure"'
    .,'eg/make -j/exec 'norm A || die "ph failed to build"'
    .,'eg/install/exec 'norm A || die "ph failed to install"'
    .,'es/ph/\<C-R>0\<CR>
endfunction

Which results in all kinds of "nope" from vim. Most of the errors are "cannot do global recursive with a range." Lots of Googling returns hits for global recursive stuff but not really anything about why this range isn't possible. Looking through some hits from this site I think I've learned I have to use the exec ... for everything not just what the :g command finds within the range, but I don't understand why. Isn't vimscript supposed to work with ex commands and these commands take ranges right?

I'd appreciate any insights and help. Thanks.

1 Answer 1

0

I asked this question because I could not understand why the global command was continually throwing errors about "recursive calls to global cannot use ranges." After digging with Google, and reflecting on what I'm writing, I realized the source of the error. I'm calling a function from the use of :g which is calling :g within the function. This is the source of the recursion. After discovering this, I turned my attention to using vim functions for what I want instead of trying to script a whole bunch of ex commands together. The end result is definitely less cryptic and does what I need it to do.

The end result function is:

function! AddDie() range
    exec 'norm f"lyt"'
    let pkg_name = getreg(0)
    let target_line = search('../configure', "n", a:lastline)
    let to_change = getline(target_line, a:lastline)
    call setline(target_line, to_change[0] . ' || die "' . pkg_name . ' failed to configure"')

    let target_line = search('make -j', "n", a:lastline)
    let to_change = getline(target_line, a:lastline)
    call setline(target_line, to_change[0] . ' || die "' . pkg_name . ' failed to build"')

    let target_line = search('install', "n", a:lastline)
    let to_change = getline(target_line, a:lastline)
    call setline(target_line, to_change[0] . ' || die "' . pkg_name . ' failed to install"')

endfunction

This does what I wanted.

4
  • 1
    FWIW, you don't need :execute 'normal! …' unless there's some weird characters or you're building the command programatically. My version of your first command would either be :normal! 0yi" or :let pkg_name = matchstr(getline('.'), '"\zs.*\ze"') or :let line = getline('.') and :let pkg_name = line[stridx(line, '"')+1:strridx(line, '"')] or something like that. But the whole thing feels like a macro: 0yi"/configure<cr>A || die "<c-r>0 failed to configure<esc>/make -j<cr>A || die "<c-r>0 failed to build"<esc>/install<cr>A || die "<c-r>0 failed to install.
    – D. Ben Knoble
    May 3, 2022 at 0:36
  • 1
    In ex, probably :normal! yi" :/configure/normal! A || "die "…, etc. But anyway, interesting post :) Note that :help E147, which the error thrown, gives more info.
    – D. Ben Knoble
    May 3, 2022 at 0:38
  • @D.BenKnoble thank you! I didn't not think to use the i motion command in that way. That is better. May 3, 2022 at 15:50
  • Yet another alternative: replace the :global calls inside the function with :substitute calls: e.g. .,'es/configure.*/& || die "ph failed to configure"
    – Rich
    Sep 30, 2022 at 11:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.