github.com/jmigpin/editor@v1.6.0/util/iout/iorw/rwedit/find.go (about) 1 package rwedit 2 3 import ( 4 "context" 5 "errors" 6 "io" 7 8 "github.com/jmigpin/editor/util/iout/iorw" 9 ) 10 11 func Find(cctx context.Context, ectx *Ctx, str string, reverse bool, opt *iorw.IndexOpt) (bool, error) { 12 if str == "" { 13 return false, nil 14 } 15 if reverse { 16 i, n, err := find2Rev(cctx, ectx, []byte(str), opt) 17 if err != nil || i < 0 { 18 return false, err 19 } 20 ectx.C.SetSelection(i+n, i) // cursor at start to allow searching next 21 } else { 22 i, n, err := find2(cctx, ectx, []byte(str), opt) 23 if err != nil || i < 0 { 24 return false, err 25 } 26 ectx.C.SetSelection(i, i+n) // cursor at end to allow searching next 27 } 28 29 return true, nil 30 } 31 func find2(cctx context.Context, ectx *Ctx, b []byte, opt *iorw.IndexOpt) (int, int, error) { 32 ci := ectx.C.Index() 33 // index to end 34 i, n, err := iorw.IndexCtx(cctx, ectx.RW, ci, b, opt) 35 if err != nil || i >= 0 { 36 return i, n, err 37 } 38 // start to index 39 e := ci + len(b) - 1 40 rd := iorw.NewLimitedReaderAt(ectx.RW, 0, e) 41 k, n, err := iorw.IndexCtx(cctx, rd, 0, b, opt) 42 if err != nil { 43 if errors.Is(err, io.EOF) { 44 return -1, 0, nil 45 } 46 return -1, 0, err 47 } 48 return k, n, nil 49 } 50 func find2Rev(cctx context.Context, ectx *Ctx, b []byte, opt *iorw.IndexOpt) (int, int, error) { 51 ci := ectx.C.Index() 52 // start to index (in reverse) 53 i, n, err := iorw.LastIndexCtx(cctx, ectx.RW, ci, b, opt) 54 if err != nil || i >= 0 { 55 return i, n, err 56 } 57 // index to end (in reverse) 58 s := ci - len(b) + 1 59 e := ectx.RW.Max() 60 rd2 := iorw.NewLimitedReaderAt(ectx.RW, s, e) 61 k, n, err := iorw.LastIndexCtx(cctx, rd2, e, b, opt) 62 if err != nil { 63 if errors.Is(err, io.EOF) { 64 return -1, 0, nil 65 } 66 return -1, 0, err 67 } 68 return k, n, nil 69 }