Den 2014-10-08 16:13, Jürgen Krämer skrev:

Hi,

BPJ schrieb am 08.10.2014 um 16:00:
Den 2014-10-02 16:33, Tim Chase skrev:
On 2014-10-02 16:17, BPJ wrote:
The other day I felt the need for a command/function which did
a :substitute on a *copy* of each line matching its search pattern
and inserted that copy below the original, unmodified line.  I soon
realized that it would be much easier to first make a copy of each
(unmodified) line, then execute the :substitute on the original
line, and lastly insert the unmodified copy above the original line
if the original line had been modified, as determined by comparing
the possibly modified original line to the always unmodified copy.

I soon found that I also had a use case for getting the modified
line above the unmodified one, so I needed a way to tell the
command/function to do that -- obviously a bang on the command and
an extra argument on the function.
[snip]
Originally I intended the command to behave similarly to :global,
defaulting to operating on the whole buffer unless an explicit
range was given, but I soon found that I sometimes wanted to find
eligible lines using :global itself and a pattern different from
the substitution pattern, and doing this with -nargs=% ended in
disaster, as the range given to :global was invisible to my
command, so my command operated on the whole file anyway (I should
have realized that to begin with, I realize! :-) The solution was
to use -range instead of -range=% and use an empty pattern on
the :AS argument if I use :g and want to use the same pattern on :s

I now have the following questions:

*   (How) can I make this simpler? (Obviously)

*   (How) can I restore the original :g-like default behavior and
still be able to use an actual :g with a separate pattern when I
want to?  N.B. that the -nargs=1 is important to me: I don't want
to have to do an extra level of escaping in the :s expression!

These two can be combined into one answer.  For your initial case,
I'd use

   :g/^/t.|s/foo/bar/ge

(the "e" flag suppresses the error in the event the line doesn't
contain "foo")

which can of course be limited by range:

   :'<,'>g/^/t.|s/foo/bar/ge

or to a subset of lines containing "baz"

   :g/baz/t.|s/foo/bar/ge


[Back from a rather bad cold...]

Thanks for the reply!

I had tried the `:g/something/t.|s/foo/bar/ge` trick, but it does what
I want only when the `:g` pattern and the `:s` pattern are the same;
otherwise it copies all lines which match the `:g` pattern, whether
the `:s` does anything to that line or not, the whole point of my
function being to avoid just that and copy only lines which are
actually affected by the `:s` -- i.e where the `:s` pattern matches,
so there is an ecological niche for my function anyway. I guess the
only way to preserve marks on the original line is to always copy it,
apply the `:s` to the copy and then delete the copy again if it is
still identical to the original line, which seems terribly wasteful
even if it makes the function simpler:

you can move the `:s` pattern to the `:g` part and reuse it by
specifying an empty pattern for `:s`, e.g.

   :g/foo/t.|s//bar/g

This ensures that only those lines are copied which will be modified by `:s`.

I have been perfectly aware of that all along, but there are cases where it makes perfect sense for the :g pattern and the :s pattern to be different -- where you want to change :s matches in and copy only lines which *also* match a :g pattern different from the :s pattern: trivially, you want to make a copy with 'bar' substituted for 'foo' of all lines containing *both *'foo' and 'baz' -- that does *not* mean that you want to make scopies of lines containing 'baz' but not containing 'foo': usually you do *not* want that!

/bpj


--
--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- You received this message because you are subscribed to the Google Groups "vim_use" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_use+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to