func replre(s string, re *sre.ReProg, to string, glob bool) string { rfrom := []rune(s) rto := []rune(to) nrefs := 0 for i := 0; i < len(rto)-1; i++ { if nb := rto[i+1]; rto[i] == '\\' { if nb >= '0' && nb <= '9' { nb -= '0' rto[i] = nb nrefs++ n := copy(rto[i+1:], rto[i+2:]) rto = rto[:i+1+n] } else if nb == '\\' { n := copy(rto[i+1:], rto[i+2:]) rto = rto[:i+1+n] } } } st := 0 for { cmd.Dprintf("re match [%d:%d]\n", st, len(rfrom)) rg := re.ExecRunes(rfrom, st, len(rfrom)) if len(rg) == 0 { break } r0 := rg[0] var ns []rune ns = append(ns, rfrom[:r0.P0]...) if nrefs == 0 { ns = append(ns, rto...) } else { for _, r := range rto { if r > 10 { ns = append(ns, r) continue } if r < rune(len(rg)) { t := rfrom[rg[r].P0:rg[r].P1] ns = append(ns, t...) } } } st = len(ns) ns = append(ns, rfrom[r0.P1:]...) rfrom = ns if !glob { break } } return string(rfrom) }
func cmdXY(s *Sam, c *Cmd) { if s.inXY { panic("can't next X or Y commands") } s.inXY = true defer func() { s.inXY = false }() var re *sre.ReProg var err error if c.Rexp != nil { if re, err = sre.Compile(c.Rexp, sre.Fwd); err != nil { panic(fmt.Sprintf("%c: regexp: %s", c.Ch, err)) } } else if c.Ch == 'Y' { panic("Y: no regexp given") } nf := make([]*file, len(s.f)) copy(nf, s.f) for _, f := range nf { matches := true if re != nil { nm := f.MenuLine() + "\n" rg := re.ExecStr(nm, 0, len(nm)) matches = len(rg) > 0 } if (c.Ch == 'X' && !matches) || (c.Ch == 'Y' && matches) { continue } c.dot = f.Sel() for _, child := range c.Child { child.dot = c.dot if err := s.runCmd(child); err != nil { s.Out <- fmt.Sprintf("%s\n", err) } } } }