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  }