func (e move) do(ed *Editor, _ io.Writer) (addr, error) { s, err := e.src.where(ed) if err != nil { return addr{}, err } d, err := e.dst.where(ed) if err != nil { return addr{}, err } d.from = d.to if d.from > s.from && d.from < s.to { return addr{}, errors.New("addresses overlap") } if d.from >= s.to { // Moving to after the source. Delete the source first. if err := pend(ed, s, runes.EmptyReader()); err != nil { return addr{}, err } } r := runes.LimitReader(ed.buf.runes.Reader(s.from), s.size()) if err := pend(ed, d, r); err != nil { return addr{}, err } if d.from <= s.from { // Moving to before the source. Delete the source second. if err := pend(ed, s, runes.EmptyReader()); err != nil { return addr{}, err } } return d, nil }
func TestEditorDoOutOfSequence(t *testing.T) { ed := NewEditor(NewBuffer()) defer ed.buf.Close() const init = "Hello, 世界" if err := ed.change(All, init); err != nil { t.Fatalf("failed to init: %v", err) } maddr := addr{5, 10} ed.marks['m'] = maddr err := ed.do(func() (addr, error) { if err := pend(ed, addr{10, 20}, runes.EmptyReader()); err != nil { panic(err) } if err := pend(ed, addr{0, 10}, runes.EmptyReader()); err != nil { panic(err) } return addr{0, 20}, nil }) if err == nil { t.Error("ed.do({out-of-sequence})=<nil>, want error") } if ed.marks['m'] != maddr { t.Errorf("ed.marks['m']=%v, want %v", ed.marks['m'], maddr) } }