github.com/jmigpin/editor@v1.6.0/util/iout/iorw/rwedit/movecursor.go (about) 1 package rwedit 2 3 import ( 4 "errors" 5 "image" 6 "io" 7 8 "github.com/jmigpin/editor/util/iout/iorw" 9 "github.com/jmigpin/editor/util/uiutil/event" 10 ) 11 12 func MoveCursorToPoint(ctx *Ctx, p image.Point, sel bool) { 13 i := ctx.Fns.GetIndex(p) 14 ctx.C.UpdateSelection(sel, i) 15 // set primary copy 16 if b, ok := ctx.Selection(); ok { 17 ctx.Fns.SetClipboardData(event.CIPrimary, string(b)) 18 } 19 } 20 21 //---------- 22 23 func MoveCursorLeft(ctx *Ctx, sel bool) error { 24 ci := ctx.C.Index() 25 _, size, err := iorw.ReadLastRuneAt(ctx.RW, ci) 26 if err != nil { 27 if errors.Is(err, io.EOF) { 28 return nil 29 } 30 return err 31 } 32 ctx.C.UpdateSelection(sel, ci-size) 33 return nil 34 } 35 func MoveCursorRight(ctx *Ctx, sel bool) error { 36 ci := ctx.C.Index() 37 _, size, err := iorw.ReadRuneAt(ctx.RW, ci) 38 if err != nil { 39 if errors.Is(err, io.EOF) { 40 return nil 41 } 42 return err 43 } 44 ctx.C.UpdateSelection(sel, ci+size) 45 return nil 46 } 47 48 //---------- 49 50 func MoveCursorUp(ctx *Ctx, sel bool) { 51 p := ctx.Fns.GetPoint(ctx.C.Index()) 52 p.Y -= ctx.Fns.LineHeight() - 1 53 i := ctx.Fns.GetIndex(p) 54 ctx.C.UpdateSelection(sel, i) 55 } 56 57 func MoveCursorDown(ctx *Ctx, sel bool) { 58 p := ctx.Fns.GetPoint(ctx.C.Index()) 59 p.Y += ctx.Fns.LineHeight() + 1 60 i := ctx.Fns.GetIndex(p) 61 ctx.C.UpdateSelection(sel, i) 62 } 63 64 //---------- 65 66 func MoveCursorJumpLeft(ctx *Ctx, sel bool) error { 67 i, err := jumpLeftIndex(ctx) 68 if err != nil { 69 return err 70 } 71 ctx.C.UpdateSelection(sel, i) 72 return nil 73 } 74 func MoveCursorJumpRight(ctx *Ctx, sel bool) error { 75 i, err := jumpRightIndex(ctx) 76 if err != nil { 77 return err 78 } 79 ctx.C.UpdateSelection(sel, i) 80 return nil 81 } 82 83 //---------- 84 85 //func MoveCursorJumpUp(ctx *Ctx, sel bool) error { 86 // return moveCursorJumpUpDown(ctx, sel, MoveCursorUp) 87 //} 88 89 //func MoveCursorJumpDown(ctx *Ctx, sel bool) error { 90 // return moveCursorJumpUpDown(ctx, sel, MoveCursorDown) 91 //} 92 93 //func moveCursorJumpUpDown(ctx *Ctx, sel bool, dirFn func(ctx *Ctx, sel bool)) error { 94 // for { 95 // i0 := ctx.C.Index() 96 // dirFn(ctx, sel) // move selection (up or down) 97 // i := ctx.C.Index() 98 99 // // break on repeated index 100 // if i == i0 { 101 // break 102 // } 103 104 // // try to go another line if it is all made of spaces 105 106 // a, b, _, err := ctx.CursorSelectionLinesIndexes() 107 // if err != nil { 108 // return err 109 // } 110 // w, err := ctx.RW.ReadFastAt(a, b-a) 111 // if err != nil { 112 // return err 113 // } 114 // allSpace := true 115 // for _, ru := range string(w) { 116 // if !unicode.IsSpace(ru) { 117 // allSpace = false 118 // break 119 // } 120 // } 121 // if allSpace { 122 // break 123 // } 124 // } 125 // return nil 126 //} 127 128 //---------- 129 130 func jumpLeftIndex(ctx *Ctx) (int, error) { 131 rd := ctx.LocalReader(ctx.C.Index()) 132 i, size, err := iorw.RuneLastIndexFn(rd, ctx.C.Index(), true, edgeOfNextWordOrNewline()) 133 if err != nil && !errors.Is(err, io.EOF) { 134 return 0, err 135 } 136 return i + size, nil 137 } 138 139 func jumpRightIndex(ctx *Ctx) (int, error) { 140 rd := ctx.LocalReader(ctx.C.Index()) 141 i, _, err := iorw.RuneIndexFn(rd, ctx.C.Index(), true, edgeOfNextWordOrNewline()) 142 if err != nil && !errors.Is(err, io.EOF) { 143 return 0, err 144 } 145 return i, nil 146 } 147 148 //---------- 149 150 func edgeOfNextWordOrNewline() func(rune) bool { 151 first := true 152 var inWord bool 153 return func(ru rune) bool { 154 w := iorw.IsWordRune(ru) 155 if first { 156 first = false 157 inWord = w 158 } else { 159 if !inWord { 160 inWord = w 161 if ru == '\n' { 162 return true 163 } 164 } else { 165 if !w { 166 return true 167 } 168 } 169 } 170 return false 171 } 172 }