diff --git a/cmd/micro/action/actions.go b/cmd/micro/action/actions.go index e913ef0a..dcb47695 100644 --- a/cmd/micro/action/actions.go +++ b/cmd/micro/action/actions.go @@ -308,6 +308,29 @@ func (h *BufHandler) ParagraphNext() bool { // Retab changes all tabs to spaces or all spaces to tabs depending // on the user's settings func (h *BufHandler) Retab() bool { + // b := h.Buf + // toSpaces := b.Settings["tabstospaces"].(bool) + // tabsize := util.IntOpt(b.Settings["tabsize"]) + // dirty := false + // + // for i := 0; i < b.LinesNum(); i++ { + // l := b.LineBytes(i) + // + // ws := util.GetLeadingWhitespace(l) + // if len(ws) != 0 { + // if toSpaces { + // ws = bytes.Replace(ws, []byte("\t"), []byte(util.Spaces(tabsize)), -1) + // } else { + // ws = bytes.Replace(ws, []byte(util.Spaces(tabsize)), []byte("\t"), -1) + // } + // } + // + // l = bytes.TrimLeft(l, " \t") + // b.lines[i].data = append(ws, l...) + // dirty = true + // } + // + // b.IsModified = dirty return true } @@ -990,8 +1013,11 @@ func (h *BufHandler) Quit() bool { quit := func() { if len(MainTab().Panes) > 1 { h.Unsplit() + } else if len(Tabs.List) > 1 { + Tabs.RemoveTab(h.splitID) } else { screen.Screen.Fini() + InfoBar.Close() os.Exit(0) } } @@ -1014,26 +1040,41 @@ func (h *BufHandler) QuitAll() bool { // AddTab adds a new tab with an empty buffer func (h *BufHandler) AddTab() bool { + width, height := screen.Screen.Size() + b := buffer.NewBufferFromString("", "", buffer.BTDefault) + tp := NewTabPane(0, 0, width, height-1, b) + Tabs.AddTab(tp) + Tabs.SetActive(len(Tabs.List) - 1) + return true } // PreviousTab switches to the previous tab in the tab list func (h *BufHandler) PreviousTab() bool { + a := Tabs.Active() + Tabs.SetActive(util.Clamp(a-1, 0, len(Tabs.List)-1)) + return false } // NextTab switches to the next tab in the tab list func (h *BufHandler) NextTab() bool { + a := Tabs.Active() + Tabs.SetActive(util.Clamp(a+1, 0, len(Tabs.List)-1)) return false } // VSplitBinding opens an empty vertical split func (h *BufHandler) VSplitBinding() bool { + h.vsplit(buffer.NewBufferFromString("", "", buffer.BTDefault)) + return false } // HSplitBinding opens an empty horizontal split func (h *BufHandler) HSplitBinding() bool { + h.hsplit(buffer.NewBufferFromString("", "", buffer.BTDefault)) + return false } @@ -1050,11 +1091,19 @@ func (h *BufHandler) Unsplit() bool { // NextSplit changes the view to the next split func (h *BufHandler) NextSplit() bool { + a := MainTab().active + a = util.Clamp(a+1, 0, len(MainTab().Panes)) + MainTab().SetActive(a) + return false } // PreviousSplit changes the view to the previous split func (h *BufHandler) PreviousSplit() bool { + a := MainTab().active + a = util.Clamp(a-1, 0, len(MainTab().Panes)) + MainTab().SetActive(a) + return false } diff --git a/cmd/micro/action/tab.go b/cmd/micro/action/tab.go index 0dd8e662..90f58a35 100644 --- a/cmd/micro/action/tab.go +++ b/cmd/micro/action/tab.go @@ -26,7 +26,6 @@ func NewTabList(bufs []*buffer.Buffer) *TabList { } tl.TabWindow = display.NewTabWindow(w, 0) tl.Names = make([]string, len(bufs)) - tl.UpdateNames() return tl } @@ -38,27 +37,58 @@ func (t *TabList) UpdateNames() { } } +func (t *TabList) AddTab(p *TabPane) { + t.List = append(t.List, p) + t.Resize() + t.UpdateNames() +} + +func (t *TabList) RemoveTab(id uint64) { + for i, p := range t.List { + if len(p.Panes) == 0 { + continue + } + if p.Panes[0].splitID == id { + copy(t.List[i:], t.List[i+1:]) + t.List[len(t.List)-1] = nil + t.List = t.List[:len(t.List)-1] + if t.Active() >= len(t.List) { + t.SetActive(len(t.List) - 1) + } + t.Resize() + t.UpdateNames() + return + } + } +} + +func (t *TabList) Resize() { + w, h := screen.Screen.Size() + InfoBar.Resize(w, h-1) + if len(t.List) > 1 { + for _, p := range t.List { + p.Y = 1 + p.Node.Resize(w, h-2) + p.Resize() + } + } else if len(t.List) == 1 { + t.List[0].Y = 0 + t.List[0].Node.Resize(w, h-1) + t.List[0].Resize() + } +} + func (t *TabList) HandleEvent(event tcell.Event) { switch e := event.(type) { case *tcell.EventResize: - w, h := screen.Screen.Size() - InfoBar.Resize(w, h-1) - if len(t.List) > 1 { - for _, p := range t.List { - p.Node.Resize(w, h-2) - p.Resize() - } - } else { - t.List[0].Node.Resize(w, h-1) - t.List[0].Resize() - } + t.Resize() case *tcell.EventMouse: mx, my := e.Position() switch e.Buttons() { case tcell.Button1: ind := t.GetMouseLoc(buffer.Loc{mx, my}) if ind != -1 { - t.Active = ind + t.SetActive(ind) } case tcell.WheelUp: if my == t.Y { @@ -72,10 +102,11 @@ func (t *TabList) HandleEvent(event tcell.Event) { } } } - t.List[t.Active].HandleEvent(event) + t.List[t.Active()].HandleEvent(event) } func (t *TabList) Display() { + t.UpdateNames() if len(t.List) > 1 { t.TabWindow.Display() } @@ -88,7 +119,7 @@ func InitTabs(bufs []*buffer.Buffer) { } func MainTab() *TabPane { - return Tabs.List[Tabs.Active] + return Tabs.List[Tabs.Active()] } // A TabPane represents a single tab @@ -185,7 +216,7 @@ func (t *TabPane) GetPane(splitid uint64) int { // Remove pane removes the pane with the given index func (t *TabPane) RemovePane(i int) { copy(t.Panes[i:], t.Panes[i+1:]) - t.Panes[len(t.Panes)-1] = nil // or the zero value of T + t.Panes[len(t.Panes)-1] = nil t.Panes = t.Panes[:len(t.Panes)-1] } diff --git a/cmd/micro/display/tabwindow.go b/cmd/micro/display/tabwindow.go index 6c1e9946..48c4c8b0 100644 --- a/cmd/micro/display/tabwindow.go +++ b/cmd/micro/display/tabwindow.go @@ -11,7 +11,7 @@ import ( type TabWindow struct { Names []string - Active int + active int Y int width int hscroll int @@ -55,6 +55,28 @@ func (w *TabWindow) TotalSize() int { return sum - 4 } +func (w *TabWindow) Active() int { + return w.active +} + +func (w *TabWindow) SetActive(a int) { + w.active = a + x := 2 + s := w.TotalSize() + for i, n := range w.Names { + c := utf8.RuneCountInString(n) + if i == a { + if x+c >= w.hscroll+w.width { + w.hscroll = util.Clamp(x+c+1-w.width, 0, s-w.width) + } else if x < w.hscroll { + w.hscroll = util.Clamp(x-4, 0, s-w.width) + } + break + } + x += c + 4 + } +} + // TODO: handle files with character width >=2 func (w *TabWindow) Display() { @@ -77,7 +99,7 @@ func (w *TabWindow) Display() { } for i, n := range w.Names { - if i == w.Active { + if i == w.active { draw('[', 1) } else { draw(' ', 1) @@ -88,7 +110,7 @@ func (w *TabWindow) Display() { if i == len(w.Names)-1 { done = true } - if i == w.Active { + if i == w.active { draw(']', 1) draw(' ', 2) } else {