X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=cmd%2Fmicro%2Fcursor.go;h=452268ba12b1f3802623be7fca8c5d33097e81e0;hb=71af765b4e4f368c4bbbcb3947f3497e17271b62;hp=c6eb92aec192c8bbe8f93055739b6b4503560c60;hpb=2041e12eba7a271edd7d2eb856f9a30bb3c00fad;p=micro.git diff --git a/cmd/micro/cursor.go b/cmd/micro/cursor.go index c6eb92ae..452268ba 100644 --- a/cmd/micro/cursor.go +++ b/cmd/micro/cursor.go @@ -1,6 +1,8 @@ package main -import "github.com/zyedidia/clipboard" +import ( + "github.com/zyedidia/clipboard" +) // The Cursor struct stores the location of the cursor in the view // The complicated part about the cursor is storing its location. @@ -21,14 +23,35 @@ type Cursor struct { // This is used for line and word selection where it is necessary // to know what the original selection was OrigSelection [2]Loc + + // Which cursor index is this (for multiple cursors) + Num int } -// Goto puts the cursor at the given cursor's location and gives the current cursor its selection too +// Goto puts the cursor at the given cursor's location and gives +// the current cursor its selection too func (c *Cursor) Goto(b Cursor) { c.X, c.Y, c.LastVisualX = b.X, b.Y, b.LastVisualX c.OrigSelection, c.CurSelection = b.OrigSelection, b.CurSelection } +// GotoLoc puts the cursor at the given cursor's location and gives +// the current cursor its selection too +func (c *Cursor) GotoLoc(l Loc) { + c.X, c.Y = l.X, l.Y + c.LastVisualX = c.GetVisualX() +} + +// CopySelection copies the user's selection to either "primary" +// or "clipboard" +func (c *Cursor) CopySelection(target string) { + if c.HasSelection() { + if target != "primary" || c.buf.Settings["useprimary"].(bool) { + clipboard.WriteAll(c.GetSelection(), target) + } + } +} + // ResetSelection resets the user's selection func (c *Cursor) ResetSelection() { c.CurSelection[0] = c.buf.Start() @@ -38,19 +61,11 @@ func (c *Cursor) ResetSelection() { // SetSelectionStart sets the start of the selection func (c *Cursor) SetSelectionStart(pos Loc) { c.CurSelection[0] = pos - // Copy to primary clipboard for linux - if c.HasSelection() { - clipboard.WriteAll(c.GetSelection(), "primary") - } } // SetSelectionEnd sets the end of the selection func (c *Cursor) SetSelectionEnd(pos Loc) { c.CurSelection[1] = pos - // Copy to primary clipboard for linux - if c.HasSelection() { - clipboard.WriteAll(c.GetSelection(), "primary") - } } // HasSelection returns whether or not the user has selected anything @@ -73,10 +88,13 @@ func (c *Cursor) DeleteSelection() { // GetSelection returns the cursor's selection func (c *Cursor) GetSelection() string { - if c.CurSelection[0].GreaterThan(c.CurSelection[1]) { - return c.buf.Substr(c.CurSelection[1], c.CurSelection[0]) + if InBounds(c.CurSelection[0], c.buf) && InBounds(c.CurSelection[1], c.buf) { + if c.CurSelection[0].GreaterThan(c.CurSelection[1]) { + return c.buf.Substr(c.CurSelection[1], c.CurSelection[0]) + } + return c.buf.Substr(c.CurSelection[0], c.CurSelection[1]) } - return c.buf.Substr(c.CurSelection[0], c.CurSelection[1]) + return "" } // SelectLine selects the current line @@ -142,7 +160,8 @@ func (c *Cursor) SelectWord() { c.Loc = c.CurSelection[1] } -// AddWordToSelection adds the word the cursor is currently on to the selection +// AddWordToSelection adds the word the cursor is currently on +// to the selection func (c *Cursor) AddWordToSelection() { if c.Loc.GreaterThan(c.OrigSelection[0]) && c.Loc.LessThan(c.OrigSelection[1]) { c.CurSelection = c.OrigSelection @@ -174,7 +193,8 @@ func (c *Cursor) AddWordToSelection() { c.Loc = c.CurSelection[1] } -// SelectTo selects from the current cursor location to the given location +// SelectTo selects from the current cursor location to the given +// location func (c *Cursor) SelectTo(loc Loc) { if loc.GreaterThan(c.OrigSelection[0]) { c.SetSelectionStart(c.OrigSelection[0]) @@ -241,19 +261,19 @@ func (c *Cursor) UpN(amount int) { proposedY := c.Y - amount if proposedY < 0 { proposedY = 0 + c.LastVisualX = 0 } else if proposedY >= c.buf.NumLines { proposedY = c.buf.NumLines - 1 } - if proposedY == c.Y { - return - } - c.Y = proposedY runes := []rune(c.buf.Line(c.Y)) - c.X = c.GetCharPosInLine(c.Y, c.LastVisualX) - if c.X > len(runes) { + c.X = c.GetCharPosInLine(proposedY, c.LastVisualX) + + if c.X > len(runes) || (amount < 0 && proposedY == c.Y) { c.X = len(runes) } + + c.Y = proposedY } // DownN moves the cursor down N lines (if possible) @@ -271,7 +291,8 @@ func (c *Cursor) Down() { c.DownN(1) } -// Left moves the cursor left one cell (if possible) or to the last line if it is at the beginning +// Left moves the cursor left one cell (if possible) or to +// the previous line if it is at the beginning func (c *Cursor) Left() { if c.Loc == c.buf.Start() { return @@ -285,7 +306,8 @@ func (c *Cursor) Left() { c.LastVisualX = c.GetVisualX() } -// Right moves the cursor right one cell (if possible) or to the next line if it is at the end +// Right moves the cursor right one cell (if possible) or +// to the next line if it is at the end func (c *Cursor) Right() { if c.Loc == c.buf.End() { return @@ -311,7 +333,21 @@ func (c *Cursor) Start() { c.LastVisualX = c.GetVisualX() } -// GetCharPosInLine gets the char position of a visual x y coordinate (this is necessary because tabs are 1 char but 4 visual spaces) +// StartOfText moves the cursor to the first non-whitespace rune of +// the line it is on +func (c *Cursor) StartOfText() { + c.Start() + for IsWhitespace(c.RuneUnder(c.X)) { + if c.X == Count(c.buf.Line(c.Y)) { + break + } + c.Right() + } +} + +// GetCharPosInLine gets the char position of a visual x y +// coordinate (this is necessary because tabs are 1 char but +// 4 visual spaces) func (c *Cursor) GetCharPosInLine(lineNum, visualPos int) int { // Get the tab size tabSize := int(c.buf.Settings["tabsize"].(float64)) @@ -330,11 +366,25 @@ func (c *Cursor) GetCharPosInLine(lineNum, visualPos int) int { func (c *Cursor) GetVisualX() int { runes := []rune(c.buf.Line(c.Y)) tabSize := int(c.buf.Settings["tabsize"].(float64)) + if c.X > len(runes) { + c.X = len(runes) - 1 + } + + if c.X < 0 { + c.X = 0 + } + return StringWidth(string(runes[:c.X]), tabSize) } -// Relocate makes sure that the cursor is inside the bounds of the buffer -// If it isn't, it moves it to be within the buffer's lines +// StoreVisualX stores the current visual x value in the cursor +func (c *Cursor) StoreVisualX() { + c.LastVisualX = c.GetVisualX() +} + +// Relocate makes sure that the cursor is inside the bounds +// of the buffer If it isn't, it moves it to be within the +// buffer's lines func (c *Cursor) Relocate() { if c.Y < 0 { c.Y = 0