Merge remote-tracking branch 'zyedidia/master' into pm

This commit is contained in:
boombuler 2016-10-01 07:20:21 +02:00
commit 8ad2179423
11 changed files with 107 additions and 14 deletions

View File

@ -17,6 +17,7 @@ build-quick:
# Same as 'build' but installs to $GOPATH/bin afterward
install: build
mkdir -p $(GOPATH)/bin
mv micro $(GOPATH)/bin
# Same as 'build-all' but installs to $GOPATH/bin afterward
@ -24,6 +25,7 @@ install-all: runtime install
# Same as 'build-quick' but installs to $GOPATH/bin afterward
install-quick: build-quick
mkdir -p $(GOPATH)/bin
mv micro $(GOPATH)/bin
# Updates tcell

View File

@ -5,7 +5,7 @@ import (
"os"
"strings"
"github.com/yosuke-furukawa/json5/encoding/json5"
"github.com/zyedidia/json5/encoding/json5"
"github.com/zyedidia/tcell"
)

View File

@ -8,6 +8,7 @@ import (
"path/filepath"
"runtime"
"strings"
"time"
"github.com/go-errors/errors"
"github.com/layeh/gopher-luar"
@ -24,6 +25,7 @@ const (
synLinesDown = 75 // How many lines down to look to do syntax highlighting
doubleClickThreshold = 400 // How many milliseconds to wait before a second click is not a double click
undoThreshold = 500 // If two events are less than n milliseconds apart, undo both of them
autosaveTime = 8 // Number of seconds to wait before autosaving
)
var (
@ -61,7 +63,8 @@ var (
// Channel of jobs running in the background
jobs chan JobFunction
// Event channel
events chan tcell.Event
events chan tcell.Event
autosave chan bool
)
// LoadInput determines which files should be loaded into buffers
@ -330,6 +333,7 @@ func main() {
jobs = make(chan JobFunction, 100)
events = make(chan tcell.Event, 100)
autosave = make(chan bool)
LoadPlugins()
@ -360,6 +364,15 @@ func main() {
}
}()
go func() {
for {
time.Sleep(autosaveTime * time.Second)
if globalSettings["autosave"].(bool) {
autosave <- true
}
}
}()
for {
// Display everything
RedrawAll()
@ -372,6 +385,8 @@ func main() {
// If a new job has finished while running in the background we should execute the callback
f.function(f.output, f.args...)
continue
case <-autosave:
CurView().Save(true)
case event = <-events:
}

File diff suppressed because one or more lines are too long

View File

@ -8,8 +8,8 @@ import (
"strconv"
"strings"
"github.com/yosuke-furukawa/json5/encoding/json5"
"github.com/zyedidia/glob"
"github.com/zyedidia/json5/encoding/json5"
)
type optionValidator func(string, interface{}) error
@ -176,6 +176,7 @@ func GetOption(name string) interface{} {
func DefaultGlobalSettings() map[string]interface{} {
return map[string]interface{}{
"autoindent": true,
"autosave": false,
"colorcolumn": float64(0),
"colorscheme": "zenburn",
"cursorline": true,
@ -199,6 +200,7 @@ func DefaultGlobalSettings() map[string]interface{} {
func DefaultLocalSettings() map[string]interface{} {
return map[string]interface{}{
"autoindent": true,
"autosave": false,
"colorcolumn": float64(0),
"cursorline": true,
"filetype": "Unknown",

View File

@ -56,6 +56,7 @@ func (l *LeafNode) VSplit(buf *Buffer) {
s := new(SplitTree)
s.kind = VerticalSplit
s.parent = l.parent
s.tabNum = l.parent.tabNum
newView := NewView(buf)
newView.TabNum = l.parent.tabNum
newView.Num = len(tab.views)
@ -81,6 +82,7 @@ func (l *LeafNode) HSplit(buf *Buffer) {
} else {
s := new(SplitTree)
s.kind = HorizontalSplit
s.tabNum = l.parent.tabNum
s.parent = l.parent
newView := NewView(buf)
newView.TabNum = l.parent.tabNum

View File

@ -44,6 +44,7 @@ func NewTabFromView(v *View) *Tab {
// SetNum sets all this tab's views to have the correct tab number
func (t *Tab) SetNum(num int) {
t.tree.tabNum = num
for _, v := range t.views {
v.TabNum = num
}

View File

@ -157,7 +157,19 @@ func GetModTime(path string) (time.Time, bool) {
// StringWidth returns the width of a string where tabs count as `tabsize` width
func StringWidth(str string, tabsize int) int {
sw := runewidth.StringWidth(str)
sw += NumOccurrences(str, '\t') * (tabsize - 1)
lineIdx := 0
for _, ch := range str {
switch ch {
case '\t':
ts := tabsize - (lineIdx % tabsize)
sw += ts - 1
lineIdx += ts
case '\n':
lineIdx = 0
default:
lineIdx++
}
}
return sw
}
@ -165,16 +177,22 @@ func StringWidth(str string, tabsize int) int {
// that have a width larger than 1 (this also counts tabs as `tabsize` width)
func WidthOfLargeRunes(str string, tabsize int) int {
count := 0
lineIdx := 0
for _, ch := range str {
var w int
if ch == '\t' {
w = tabsize
w = tabsize - (lineIdx % tabsize)
} else {
w = runewidth.RuneWidth(ch)
}
if w > 1 {
count += (w - 1)
}
if ch == '\n' {
lineIdx = 0
} else {
lineIdx += w
}
}
return count
}

View File

@ -116,3 +116,41 @@ func TestJoinAndSplitCommandArgs(t *testing.T) {
}
}
}
func TestStringWidth(t *testing.T) {
tabsize := 4
if w := StringWidth("1\t2", tabsize); w != 5 {
t.Error("StringWidth 1 Failed. Got", w)
}
if w := StringWidth("\t", tabsize); w != 4 {
t.Error("StringWidth 2 Failed. Got", w)
}
if w := StringWidth("1\t", tabsize); w != 4 {
t.Error("StringWidth 3 Failed. Got", w)
}
if w := StringWidth("\t\t", tabsize); w != 8 {
t.Error("StringWidth 4 Failed. Got", w)
}
if w := StringWidth("12\t2\t", tabsize); w != 8 {
t.Error("StringWidth 5 Failed. Got", w)
}
}
func TestWidthOfLargeRunes(t *testing.T) {
tabsize := 4
if w := WidthOfLargeRunes("1\t2", tabsize); w != 2 {
t.Error("WidthOfLargeRunes 1 Failed. Got", w)
}
if w := WidthOfLargeRunes("\t", tabsize); w != 3 {
t.Error("WidthOfLargeRunes 2 Failed. Got", w)
}
if w := WidthOfLargeRunes("1\t", tabsize); w != 2 {
t.Error("WidthOfLargeRunes 3 Failed. Got", w)
}
if w := WidthOfLargeRunes("\t\t", tabsize); w != 6 {
t.Error("WidthOfLargeRunes 4 Failed. Got", w)
}
if w := WidthOfLargeRunes("12\t2\t", tabsize); w != 3 {
t.Error("WidthOfLargeRunes 5 Failed. Got", w)
}
}

View File

@ -38,7 +38,7 @@ type View struct {
// Specifies whether or not this view holds a help buffer
Type ViewType
// Actual with and height
// Actual width and height
width int
height int
@ -194,7 +194,13 @@ func (v *View) ScrollDown(n int) {
// causing them to lose the unsaved changes
func (v *View) CanClose() bool {
if v.Type == vtDefault && v.Buf.IsModified {
char, canceled := messenger.LetterPrompt("Save changes to "+v.Buf.Name+" before closing? (y,n,esc) ", 'y', 'n')
var char rune
var canceled bool
if v.Buf.Settings["autosave"].(bool) {
char = 'y'
} else {
char, canceled = messenger.LetterPrompt("Save changes to "+v.Buf.Name+" before closing? (y,n,esc) ", 'y', 'n')
}
if !canceled {
if char == 'y' {
v.Save(true)
@ -709,6 +715,8 @@ func (v *View) DisplayView() {
// Now we actually draw the line
colN := 0
strWidth := 0
tabSize := int(v.Buf.Settings["tabsize"].(float64))
for _, ch := range line {
lineStyle := defStyle
@ -770,8 +778,9 @@ func (v *View) DisplayView() {
v.drawCell(screenX-v.leftCol, screenY, indentChar[0], nil, lineIndentStyle)
}
// Now the tab has to be displayed as a bunch of spaces
tabSize := int(v.Buf.Settings["tabsize"].(float64))
for i := 0; i < tabSize-1; i++ {
visLoc := strWidth
remainder := tabSize - (visLoc % tabSize)
for i := 0; i < remainder-1; i++ {
screenX++
if screenX-v.x-v.leftCol >= v.lineNumOffset {
v.drawCell(screenX-v.leftCol, screenY, ' ', nil, lineStyle)
@ -795,6 +804,7 @@ func (v *View) DisplayView() {
charNum = charNum.Move(1, v.Buf)
screenX++
colN++
strWidth += StringWidth(string(ch), tabSize)
}
// Here we are at a newline
@ -825,15 +835,13 @@ func (v *View) DisplayView() {
}
if screenX-v.x-v.leftCol+i >= v.lineNumOffset {
colorcolumn := int(v.Buf.Settings["colorcolumn"].(float64))
if colorcolumn != 0 && screenX-v.leftCol+i == colorcolumn-1 {
if colorcolumn != 0 && screenX-v.lineNumOffset+i == colorcolumn-1 {
if style, ok := colorscheme["color-column"]; ok {
fg, _, _ := style.Decompose()
lineStyle = lineStyle.Background(fg)
}
v.drawCell(screenX-v.leftCol+i, screenY, ' ', nil, lineStyle)
} else {
v.drawCell(screenX-v.leftCol+i, screenY, ' ', nil, lineStyle)
}
v.drawCell(screenX-v.leftCol+i, screenY, ' ', nil, lineStyle)
}
}
}

View File

@ -93,6 +93,13 @@ Here are the options that you can set:
default value: `2`
* `autosave`: micro will save the buffer every 8 seconds automatically.
Micro also will automatically save and quit when you exit without asking.
Be careful when using this feature, because you might accidentally save a file,
overwriting what was there before.
default value: `off`
---
Default plugin options: