github.com/jmigpin/editor@v1.6.0/util/iout/iorw/rwedit/replace.go (about)

     1  package rwedit
     2  
     3  import (
     4  	"github.com/jmigpin/editor/util/iout/iorw"
     5  )
     6  
     7  func Replace(ctx *Ctx, old, new string) (bool, error) {
     8  	if old == "" {
     9  		return false, nil
    10  	}
    11  
    12  	oldb := []byte(old)
    13  	newb := []byte(new)
    14  
    15  	a, b, ok := ctx.C.SelectionIndexes()
    16  	if !ok {
    17  		a = ctx.RW.Min()
    18  		b = ctx.RW.Max()
    19  	}
    20  
    21  	ci, replaced, err := replace2(ctx, oldb, newb, a, b)
    22  	if err != nil {
    23  		return replaced, err
    24  	}
    25  	ctx.C.SetIndex(ci)
    26  	return replaced, nil
    27  }
    28  
    29  func replace2(ctx *Ctx, oldb, newb []byte, a, b int) (int, bool, error) {
    30  	ci := ctx.C.Index()
    31  	replaced := false
    32  	for a < b {
    33  		rd := iorw.NewLimitedReaderAt(ctx.RW, a, b)
    34  		i, _, err := iorw.Index(rd, a, oldb, false)
    35  		if err != nil {
    36  			return ci, replaced, err
    37  		}
    38  		if i < 0 {
    39  			return ci, replaced, nil
    40  		}
    41  		if err := ctx.RW.OverwriteAt(i, len(oldb), newb); err != nil {
    42  			return ci, replaced, err
    43  		}
    44  		replaced = true
    45  		d := -len(oldb) + len(newb)
    46  		b += d
    47  		a = i + len(newb)
    48  
    49  		if i < ci {
    50  			ci += d
    51  			if ci < i {
    52  				ci = i
    53  			}
    54  		}
    55  	}
    56  	return ci, replaced, nil
    57  }