Back References in a range

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Back References in a range

Andrew Long
Hi all

I'm trying to bound a substitution to the legal range of a procedure
body. This can be either ?^PROCBEGIN\>?,/^PROCEND\>/ or ?^BEGIN\>?,
\^END/>/.

First I tried to a single pattern like this:-

:?^\(PROC\)\=BEGIN\>?,\^\(PROC\)\=END\>/

But this isn't quire right 'cos it'll terminate early or late if the
PROC's don't balance. Next I tried using '\&' to try to catch the first
\(PROC\) (or empty reference)

:?^\(PROC\)\=BEGIN\>?,\^\&END\>/

That didn't work because it was trying to match the WHOLE match. Next I
tried to use a back reference in the TO line :-

:?^\(PROC\)\=BEGIN\>?,\^\1END\>/

But I got an error 'E65: Illegal back reference'. 'he E65' just took me
back to the help page that I'd first found when I was looking for how to
do this.

I've tried using '$1' (grasping at straws, here!) but that just said 'no
match'.

Any ideas, please?

--
Andrew Long
Newcastle upon Tyne, Great Britain
============================================================

Reply | Threaded
Open this post in threaded view
|

Re: Back References in a range

Charles E Campbell Jr
Andrew Long wrote:

>I'm trying to bound a substitution to the legal range of a procedure
>body. This can be either ?^PROCBEGIN\>?,/^PROCEND\>/ or ?^BEGIN\>?,
>\^END/>/.
>
>First I tried to a single pattern like this:-
>
>:?^\(PROC\)\=BEGIN\>?,\^\(PROC\)\=END\>/
>
>But this isn't quire right 'cos it'll terminate early or late if the
>PROC's don't balance.
>

:?^PROCBEGIN\>?;/^PROCEND\>/p
:?^BEGIN\>?;/^END\>/p

is probably the best you can do.  Note the semi-colon is used instead of
a comma.
If you're trying syntax highlighting, then you can use \z1 to catch the
PROC; otherwise,
you can't simply get it.   Now, with some vimL:

fun! ProcZone()
"  call Dfunc("ProcZone()")
  let line1   = search('^\(PROC\)\=BEGIN\>','bW')
  let procpat = substitute(getline("."),'\(PROC\)\=BEGIN\>','\1','')
  let line2   = search(procpat.'END\>','W')
  let ret     = line1.','.line2
"  call Dret("ProcZone ".ret)
  return ret
endfun

You can pass some argument and use exe... with it, etc.

Regards,
Chip  Campbell

Reply | Threaded
Open this post in threaded view
|

Re: Back References in a range

Tim Chase-2
 > First I tried to a single pattern like this:-
 >
 > :?^\(PROC\)\=BEGIN\>?,\^\(PROC\)\=END\>/
 >
 > But this isn't quire right 'cos it'll terminate early or
 > late if the PROC's don't balance.

To do something like this, you may have to use a call to
exec() and build your targets.  Dr. Chip's solution was a
nice stopgap though.

The trick would be to do something like this 100% untested
stab where "#" is the action you want to perform on this
range:

:?^\(PROC\)\=BEGIN\>?exec(".,/^".substitute(getline("."),
'^\(PROC\)\=.*', '\1', '').'END\>/#')

(all one line in case my mailer mungs it)

It should search backwards for the first matching line in
question (your "\(PROC\)\=BEGIN" line), and then uses the
exec() call the range created by determining which type of
line it's currently sitting on.  Thus it will exec() one of
the following on the line it finds:

     .,/^PROCEND\>/#

or

     .,/^END\>/#

depending on whether the first line begins with "PROC" or
not.

It does involve hacking your desired command ("#" in this
case) inside the string passed to exec, but at least it
should do what you're hoping to.

-tim