github.com/jmigpin/editor@v1.6.0/util/iout/iorw/rwedit/input.go (about) 1 package rwedit 2 3 import ( 4 "errors" 5 "io" 6 "unicode" 7 8 "github.com/jmigpin/editor/util/uiutil/event" 9 ) 10 11 //godebug:annotatefile 12 13 func HandleInput(ctx *Ctx, ev interface{}) (event.Handled, error) { 14 in := &Input{ctx, ev} 15 return in.handle() 16 } 17 18 //---------- 19 20 type Input struct { 21 ctx *Ctx 22 ev interface{} 23 } 24 25 func (in *Input) handle() (event.Handled, error) { 26 switch ev := in.ev.(type) { 27 case *event.KeyDown: 28 return in.onKeyDown(ev) 29 case *event.MouseDown: 30 return in.onMouseDown(ev) 31 case *event.MouseDragMove: 32 return in.onMouseDragMove(ev) 33 case *event.MouseDragEnd: 34 return in.onMouseDragEnd(ev) 35 case *event.MouseClick: 36 return in.onMouseClick(ev) 37 case *event.MouseDoubleClick: 38 return in.onMouseDoubleClick(ev) 39 case *event.MouseTripleClick: 40 return in.onMouseTripleClick(ev) 41 } 42 return false, nil 43 } 44 45 //---------- 46 47 func (in *Input) onMouseDown(ev *event.MouseDown) (event.Handled, error) { 48 switch ev.Button { 49 case event.ButtonLeft: 50 if ev.Mods.ClearLocks().Is(event.ModShift) { 51 MoveCursorToPoint(in.ctx, ev.Point, true) 52 } else { 53 MoveCursorToPoint(in.ctx, ev.Point, false) 54 } 55 return true, nil 56 case event.ButtonWheelUp: 57 ScrollUp(in.ctx, true) 58 case event.ButtonWheelDown: 59 ScrollUp(in.ctx, false) 60 } 61 return false, nil 62 } 63 64 //---------- 65 66 func (in *Input) onMouseDragMove(ev *event.MouseDragMove) (event.Handled, error) { 67 if ev.Buttons.Has(event.ButtonLeft) { 68 MoveCursorToPoint(in.ctx, ev.Point, true) 69 return true, nil 70 } 71 return false, nil 72 } 73 func (in *Input) onMouseDragEnd(ev *event.MouseDragEnd) (event.Handled, error) { 74 switch ev.Button { 75 case event.ButtonLeft: 76 MoveCursorToPoint(in.ctx, ev.Point, true) 77 return true, nil 78 } 79 return false, nil 80 } 81 82 //---------- 83 84 func (in *Input) onMouseClick(ev *event.MouseClick) (event.Handled, error) { 85 switch ev.Button { 86 case event.ButtonMiddle: 87 MoveCursorToPoint(in.ctx, ev.Point, false) 88 Paste(in.ctx, event.CIPrimary) 89 return true, nil 90 } 91 return false, nil 92 } 93 94 func (in *Input) onMouseDoubleClick(ev *event.MouseDoubleClick) (event.Handled, error) { 95 switch ev.Button { 96 case event.ButtonLeft: 97 MoveCursorToPoint(in.ctx, ev.Point, false) 98 err := SelectWord(in.ctx) 99 // can select at EOF but avoid error msg 100 if errors.Is(err, io.EOF) { 101 err = nil 102 } 103 104 return true, err 105 } 106 return false, nil 107 } 108 109 func (in *Input) onMouseTripleClick(ev *event.MouseTripleClick) (event.Handled, error) { 110 switch ev.Button { 111 case event.ButtonLeft: 112 MoveCursorToPoint(in.ctx, ev.Point, false) 113 err := SelectLine(in.ctx) 114 return true, err 115 } 116 return false, nil 117 } 118 119 //---------- 120 121 func (in *Input) onKeyDown(ev *event.KeyDown) (_ event.Handled, err error) { 122 mcl := ev.Mods.ClearLocks() 123 124 makeCursorVisible := func() { 125 if err == nil { 126 in.ctx.Fns.MakeIndexVisible(in.ctx.C.Index()) 127 } 128 } 129 130 switch ev.KeySym { 131 case event.KSymAltL, 132 event.KSymAltGr, 133 event.KSymShiftL, 134 event.KSymShiftR, 135 event.KSymControlL, 136 event.KSymControlR, 137 event.KSymCapsLock, 138 event.KSymNumLock, 139 event.KSymInsert, 140 event.KSymEscape, 141 event.KSymSuperL: // windows key 142 // ignore these 143 case event.KSymRight: 144 switch { 145 case mcl.Is(event.ModCtrl | event.ModShift): 146 err = MoveCursorJumpRight(in.ctx, true) 147 case mcl.Is(event.ModCtrl): 148 err = MoveCursorJumpRight(in.ctx, false) 149 case mcl.Is(event.ModShift): 150 err = MoveCursorRight(in.ctx, true) 151 default: 152 err = MoveCursorRight(in.ctx, false) 153 } 154 makeCursorVisible() 155 return true, err 156 case event.KSymLeft: 157 switch { 158 case mcl.Is(event.ModCtrl | event.ModShift): 159 err = MoveCursorJumpLeft(in.ctx, true) 160 case mcl.Is(event.ModCtrl): 161 err = MoveCursorJumpLeft(in.ctx, false) 162 case mcl.Is(event.ModShift): 163 err = MoveCursorLeft(in.ctx, true) 164 default: 165 err = MoveCursorLeft(in.ctx, false) 166 } 167 makeCursorVisible() 168 return true, err 169 case event.KSymUp: 170 switch { 171 case mcl.Is(event.ModCtrl | event.ModAlt): 172 err = MoveLineUp(in.ctx) 173 //case mcl.Is(event.ModCtrl | event.ModShift): 174 //err = MoveCursorJumpUp(in.ctx, true) 175 //case mcl.Is(event.ModCtrl): 176 //err = MoveCursorJumpUp(in.ctx, false) 177 case mcl.HasAny(event.ModShift): 178 MoveCursorUp(in.ctx, true) 179 default: 180 MoveCursorUp(in.ctx, false) 181 } 182 makeCursorVisible() 183 return true, err 184 case event.KSymDown: 185 switch { 186 case mcl.Is(event.ModCtrl | event.ModShift | event.ModAlt): 187 err = DuplicateLines(in.ctx) 188 case mcl.Is(event.ModCtrl | event.ModAlt): 189 err = MoveLineDown(in.ctx) 190 //case mcl.Is(event.ModCtrl | event.ModShift): 191 //err = MoveCursorJumpDown(in.ctx, true) 192 //case mcl.Is(event.ModCtrl): 193 //err = MoveCursorJumpDown(in.ctx, false) 194 case mcl.HasAny(event.ModShift): 195 MoveCursorDown(in.ctx, true) 196 default: 197 MoveCursorDown(in.ctx, false) 198 } 199 makeCursorVisible() 200 return true, err 201 case event.KSymHome: 202 switch { 203 case mcl.Is(event.ModCtrl | event.ModShift): 204 StartOfString(in.ctx, true) 205 case mcl.Is(event.ModCtrl): 206 StartOfString(in.ctx, false) 207 case mcl.Is(event.ModShift): 208 err = StartOfLine(in.ctx, true) 209 default: 210 err = StartOfLine(in.ctx, false) 211 } 212 makeCursorVisible() 213 return true, err 214 case event.KSymEnd: 215 switch { 216 case mcl.Is(event.ModCtrl | event.ModShift): 217 EndOfString(in.ctx, true) 218 case mcl.Is(event.ModCtrl): 219 EndOfString(in.ctx, false) 220 case mcl.Is(event.ModShift): 221 err = EndOfLine(in.ctx, true) 222 default: 223 err = EndOfLine(in.ctx, false) 224 } 225 makeCursorVisible() 226 return true, err 227 case event.KSymBackspace: 228 err = Backspace(in.ctx) 229 makeCursorVisible() 230 return true, err 231 case event.KSymDelete: 232 err = Delete(in.ctx) 233 makeCursorVisible() // TODO: on delete? 234 return true, err 235 case event.KSymReturn: 236 err = AutoIndent(in.ctx) 237 makeCursorVisible() 238 return true, err 239 case event.KSymTabLeft: 240 err = TabLeft(in.ctx) 241 makeCursorVisible() 242 return true, err 243 case event.KSymTab: 244 switch { 245 case mcl.Is(event.ModShift): 246 // TODO: using KSymTabLeft case, this still needed? 247 err = TabLeft(in.ctx) 248 default: 249 err = TabRight(in.ctx) 250 } 251 makeCursorVisible() 252 return true, err 253 case event.KSymSpace: 254 // ensure space even if modifiers are present 255 err = InsertString(in.ctx, " ") 256 makeCursorVisible() 257 return true, err 258 case event.KSymPageUp: 259 PageUp(in.ctx, true) 260 return true, nil 261 case event.KSymPageDown: 262 PageUp(in.ctx, false) 263 return true, nil 264 default: 265 switch { 266 case mcl.Is(event.ModCtrl): 267 switch ev.KeySym { 268 case event.KSymD: 269 err = Comment(in.ctx) 270 return true, err 271 case event.KSymC: 272 err = Copy(in.ctx) 273 return true, err 274 case event.KSymX: 275 err = Cut(in.ctx) 276 return true, err 277 case event.KSymV: 278 Paste(in.ctx, event.CIClipboard) 279 return true, nil 280 case event.KSymK: 281 err = RemoveLines(in.ctx) 282 return true, nil 283 case event.KSymA: 284 err = SelectAll(in.ctx) 285 return true, nil 286 case event.KSymZ: 287 err = Undo(in.ctx) 288 return true, nil 289 } 290 case mcl.Is(event.ModCtrl | event.ModShift): 291 switch ev.KeySym { 292 case event.KSymD: 293 err = Uncomment(in.ctx) 294 return true, err 295 case event.KSymZ: 296 err = Redo(in.ctx) 297 return true, nil 298 } 299 case ev.KeySym >= event.KSymF1 && ev.KeySym <= event.KSymF12: 300 // do nothing 301 case !unicode.IsPrint(ev.Rune): 302 // do nothing 303 default: 304 err = InsertString(in.ctx, string(ev.Rune)) 305 makeCursorVisible() 306 return true, err 307 } 308 } 309 return false, nil 310 }