github.com/jmigpin/editor@v1.6.0/util/iout/iorw/rwedit/moveline.go (about) 1 package rwedit 2 3 import ( 4 "github.com/jmigpin/editor/util/iout" 5 "github.com/jmigpin/editor/util/iout/iorw" 6 ) 7 8 func MoveLineUp(ctx *Ctx) error { 9 a, b, newline, err := ctx.CursorSelectionLinesIndexes() 10 if err != nil { 11 return err 12 } 13 // already at the first line 14 if a <= ctx.RW.Min() { 15 return nil 16 } 17 18 s0, err := ctx.RW.ReadFastAt(a, b-a) 19 if err != nil { 20 return err 21 } 22 s := iout.CopyBytes(s0) 23 24 if err := ctx.RW.OverwriteAt(a, b-a, nil); err != nil { 25 return err 26 } 27 28 rd := ctx.LocalReader(a - 1) 29 a2, err := iorw.LineStartIndex(rd, a-1) // start of previous line, -1 is size of '\n' 30 if err != nil { 31 return err 32 } 33 34 // remove newline to honor the moving line 35 if !newline { 36 if err := ctx.RW.OverwriteAt(a-1, 1, nil); err != nil { 37 return err 38 } 39 s = append(s, '\n') 40 } 41 42 if err := ctx.RW.OverwriteAt(a2, 0, s); err != nil { 43 return err 44 } 45 46 if ctx.C.HaveSelection() { 47 b2 := a2 + len(s) 48 _, size, err := iorw.ReadLastRuneAt(ctx.RW, b2) 49 if err != nil { 50 return nil 51 } 52 ctx.C.SetSelection(a2, b2-size) 53 } else { 54 // position cursor at same position 55 ctx.C.SetIndex(ctx.C.Index() - (a - a2)) 56 } 57 return nil 58 } 59 60 func MoveLineDown(ctx *Ctx) error { 61 a, b, newline, err := ctx.CursorSelectionLinesIndexes() 62 if err != nil { 63 return err 64 } 65 // already at the last line 66 if !newline && b >= ctx.RW.Max() { 67 return nil 68 } 69 70 // keep copy of the moving line 71 s0, err := ctx.RW.ReadFastAt(a, b-a) 72 if err != nil { 73 return err 74 } 75 s := iout.CopyBytes(s0) 76 77 // delete moving line 78 if err := ctx.RW.OverwriteAt(a, b-a, nil); err != nil { 79 return err 80 } 81 82 // line end of the line below 83 rd2 := ctx.LocalReader(a) 84 a2, newline, err := iorw.LineEndIndex(rd2, a) 85 if err != nil { 86 return err 87 } 88 89 // remove newline 90 if !newline { 91 // remove newline 92 s = s[:len(s)-1] 93 // insert newline 94 if err := ctx.RW.OverwriteAt(a2, 0, []byte{'\n'}); err != nil { 95 return err 96 } 97 a2 += 1 // 1 is '\n' added to s before insertion 98 } 99 100 if err := ctx.RW.OverwriteAt(a2, 0, s); err != nil { 101 return err 102 } 103 104 if ctx.C.HaveSelection() { 105 b2 := a2 + len(s) 106 // don't select newline 107 if newline { 108 _, size, err := iorw.ReadLastRuneAt(ctx.RW, b2) 109 if err != nil { 110 return nil 111 } 112 b2 -= size 113 } 114 ctx.C.SetSelection(a2, b2) 115 } else { 116 // position cursor at same position 117 ctx.C.SetIndex(ctx.C.Index() + (a2 - a)) 118 } 119 return nil 120 }