Search code examples
vimneovim

vim: Search replace complex within each class


I have many nested classes in a file. Each similar to this, but with different IDs in the ProtoMember(ID).

public class ApiInputs 
{
    [ProtoMember(316)]
    [JsonPropertyName("Meta")] 
    public Meta Meta { get; set; }

    [ProtoMember(317)]
    [JsonPropertyName("Settings")] 
    public Settings? Settings { get; set; }

    [ProtoMember(318)]
    [JsonPropertyName("Weight")] 
    public Weight? Weight { get; set; }
}

I want to replace the IDs within each class starting each time at 1 instead of 316 (in this class). I can global replace all with "%%%%" and then use a vim command like the following to replace like I want if I only had one class. But, I need to reset the counter in each class.

:let i=1 | g/%%%%/s//\=i/ | let i = i+1

I've tried several (intermediate skill) vim commands and macros and successfully hung both of my vim editors a few times. So, how can I tell the macro or the command line to make this change within each class, restarting the counter each time.

Possible without a hack? or better to awk?

and


Solution

  • The trick would be to increment the counter inside the substitute expression using silent execute() and another execute() to check if we entered a new class to reset the counter:

    :let i = 1 | %s/\(public class\_.\{-}\)\?ProtoMember(\zs\d\+\ze)/\=execute('if !empty(submatch(1)) | let i = 1 | endif') .. i .. execute('let i = i + 1')/
    

    will give:

    public class ApiInputs 
    {
        [ProtoMember(1)]
        [JsonPropertyName("Meta")] 
        public Meta Meta { get; set; }
    
        [ProtoMember(2)]
        [JsonPropertyName("Settings")] 
        public Settings? Settings { get; set; }
    
        [ProtoMember(3)]
        [JsonPropertyName("Weight")] 
        public Weight? Weight { get; set; }
    }
    
    public class ApiOutputs 
    {
        [ProtoMember(1)]
        [JsonPropertyName("Meta")] 
        public Meta Meta { get; set; }
    
        [ProtoMember(2)]
        [JsonPropertyName("Settings")] 
        public Settings? Settings { get; set; }
    
        [ProtoMember(3)]
        [JsonPropertyName("Weight")] 
        public Weight? Weight { get; set; }
    }