From 18f9b6f34ef552fdd8174b8865961ed5d83915ec Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Fri, 5 May 2017 12:04:18 -0400 Subject: [PATCH] Add tabmovement option This option makes micro treat spaces at the beginning of lines as if they are tabs. This option only does anything if tabstospaces is already on. E.g. micro will move over 4 spaces at once when at the start of a line. Closes #616 --- cmd/micro/actions.go | 32 ++++++++++++++++++++++++++++++-- cmd/micro/settings.go | 2 ++ cmd/micro/util.go | 10 ++++++++++ runtime/help/options.md | 5 +++++ 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/cmd/micro/actions.go b/cmd/micro/actions.go index 3c6f48b2..7d726b08 100644 --- a/cmd/micro/actions.go +++ b/cmd/micro/actions.go @@ -111,7 +111,21 @@ func (v *View) CursorLeft(usePlugin bool) bool { v.Cursor.Loc = v.Cursor.CurSelection[0] v.Cursor.ResetSelection() } else { - v.Cursor.Left() + tabstospaces := v.Buf.Settings["tabstospaces"].(bool) + tabmovement := v.Buf.Settings["tabmovement"].(bool) + if tabstospaces && tabmovement { + tabsize := int(v.Buf.Settings["tabsize"].(float64)) + line := v.Buf.Line(v.Cursor.Y) + if v.Cursor.X-tabsize >= 0 && line[v.Cursor.X-tabsize:v.Cursor.X] == Spaces(tabsize) && IsStrWhitespace(line[0:v.Cursor.X-tabsize]) { + for i := 0; i < tabsize; i++ { + v.Cursor.Left() + } + } else { + v.Cursor.Left() + } + } else { + v.Cursor.Left() + } } if usePlugin { @@ -130,7 +144,21 @@ func (v *View) CursorRight(usePlugin bool) bool { v.Cursor.Loc = v.Cursor.CurSelection[1].Move(-1, v.Buf) v.Cursor.ResetSelection() } else { - v.Cursor.Right() + tabstospaces := v.Buf.Settings["tabstospaces"].(bool) + tabmovement := v.Buf.Settings["tabmovement"].(bool) + if tabstospaces && tabmovement { + tabsize := int(v.Buf.Settings["tabsize"].(float64)) + line := v.Buf.Line(v.Cursor.Y) + if v.Cursor.X+tabsize < Count(line) && line[v.Cursor.X:v.Cursor.X+tabsize] == Spaces(tabsize) && IsStrWhitespace(line[0:v.Cursor.X]) { + for i := 0; i < tabsize; i++ { + v.Cursor.Right() + } + } else { + v.Cursor.Right() + } + } else { + v.Cursor.Right() + } } if usePlugin { diff --git a/cmd/micro/settings.go b/cmd/micro/settings.go index 560a1716..c0ed53b3 100644 --- a/cmd/micro/settings.go +++ b/cmd/micro/settings.go @@ -196,6 +196,7 @@ func DefaultGlobalSettings() map[string]interface{} { "splitBottom": true, "statusline": true, "syntax": true, + "tabmovement": false, "tabsize": float64(4), "tabstospaces": false, "termtitle": false, @@ -231,6 +232,7 @@ func DefaultLocalSettings() map[string]interface{} { "splitBottom": true, "statusline": true, "syntax": true, + "tabmovement": false, "tabsize": float64(4), "tabstospaces": false, "useprimary": true, diff --git a/cmd/micro/util.go b/cmd/micro/util.go index 5b2cfac8..25d209d7 100644 --- a/cmd/micro/util.go +++ b/cmd/micro/util.go @@ -82,6 +82,16 @@ func IsWhitespace(c rune) bool { return c == ' ' || c == '\t' || c == '\n' } +// IsStrWhitespace returns true if the given string is all whitespace +func IsStrWhitespace(str string) bool { + for _, c := range str { + if !IsWhitespace(c) { + return false + } + } + return true +} + // Contains returns whether or not a string array contains a given string func Contains(list []string, a string) bool { for _, b := range list { diff --git a/runtime/help/options.md b/runtime/help/options.md index 40ac5eb5..03fb2522 100644 --- a/runtime/help/options.md +++ b/runtime/help/options.md @@ -65,6 +65,11 @@ Here are the options that you can set: default value: `off` +* `tabmovement`: navigate spaces at the beginning of lines as if they are tabs (e.g. move over 4 spaces at once). + This option only does anything if `tabstospaces` is on. + + default value: `off` + * `autoindent`: when creating a new line use the same indentation as the previous line