mirror of
https://github.com/zyedidia/micro.git
synced 2026-03-25 18:07:07 +09:00
Better tab mUI
This commit is contained in:
@@ -308,6 +308,29 @@ func (h *BufHandler) ParagraphNext() bool {
|
|||||||
// Retab changes all tabs to spaces or all spaces to tabs depending
|
// Retab changes all tabs to spaces or all spaces to tabs depending
|
||||||
// on the user's settings
|
// on the user's settings
|
||||||
func (h *BufHandler) Retab() bool {
|
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
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -990,8 +1013,11 @@ func (h *BufHandler) Quit() bool {
|
|||||||
quit := func() {
|
quit := func() {
|
||||||
if len(MainTab().Panes) > 1 {
|
if len(MainTab().Panes) > 1 {
|
||||||
h.Unsplit()
|
h.Unsplit()
|
||||||
|
} else if len(Tabs.List) > 1 {
|
||||||
|
Tabs.RemoveTab(h.splitID)
|
||||||
} else {
|
} else {
|
||||||
screen.Screen.Fini()
|
screen.Screen.Fini()
|
||||||
|
InfoBar.Close()
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1014,26 +1040,41 @@ func (h *BufHandler) QuitAll() bool {
|
|||||||
|
|
||||||
// AddTab adds a new tab with an empty buffer
|
// AddTab adds a new tab with an empty buffer
|
||||||
func (h *BufHandler) AddTab() bool {
|
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
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// PreviousTab switches to the previous tab in the tab list
|
// PreviousTab switches to the previous tab in the tab list
|
||||||
func (h *BufHandler) PreviousTab() bool {
|
func (h *BufHandler) PreviousTab() bool {
|
||||||
|
a := Tabs.Active()
|
||||||
|
Tabs.SetActive(util.Clamp(a-1, 0, len(Tabs.List)-1))
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextTab switches to the next tab in the tab list
|
// NextTab switches to the next tab in the tab list
|
||||||
func (h *BufHandler) NextTab() bool {
|
func (h *BufHandler) NextTab() bool {
|
||||||
|
a := Tabs.Active()
|
||||||
|
Tabs.SetActive(util.Clamp(a+1, 0, len(Tabs.List)-1))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// VSplitBinding opens an empty vertical split
|
// VSplitBinding opens an empty vertical split
|
||||||
func (h *BufHandler) VSplitBinding() bool {
|
func (h *BufHandler) VSplitBinding() bool {
|
||||||
|
h.vsplit(buffer.NewBufferFromString("", "", buffer.BTDefault))
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// HSplitBinding opens an empty horizontal split
|
// HSplitBinding opens an empty horizontal split
|
||||||
func (h *BufHandler) HSplitBinding() bool {
|
func (h *BufHandler) HSplitBinding() bool {
|
||||||
|
h.hsplit(buffer.NewBufferFromString("", "", buffer.BTDefault))
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1050,11 +1091,19 @@ func (h *BufHandler) Unsplit() bool {
|
|||||||
|
|
||||||
// NextSplit changes the view to the next split
|
// NextSplit changes the view to the next split
|
||||||
func (h *BufHandler) NextSplit() bool {
|
func (h *BufHandler) NextSplit() bool {
|
||||||
|
a := MainTab().active
|
||||||
|
a = util.Clamp(a+1, 0, len(MainTab().Panes))
|
||||||
|
MainTab().SetActive(a)
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// PreviousSplit changes the view to the previous split
|
// PreviousSplit changes the view to the previous split
|
||||||
func (h *BufHandler) PreviousSplit() bool {
|
func (h *BufHandler) PreviousSplit() bool {
|
||||||
|
a := MainTab().active
|
||||||
|
a = util.Clamp(a-1, 0, len(MainTab().Panes))
|
||||||
|
MainTab().SetActive(a)
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ func NewTabList(bufs []*buffer.Buffer) *TabList {
|
|||||||
}
|
}
|
||||||
tl.TabWindow = display.NewTabWindow(w, 0)
|
tl.TabWindow = display.NewTabWindow(w, 0)
|
||||||
tl.Names = make([]string, len(bufs))
|
tl.Names = make([]string, len(bufs))
|
||||||
tl.UpdateNames()
|
|
||||||
|
|
||||||
return tl
|
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) {
|
func (t *TabList) HandleEvent(event tcell.Event) {
|
||||||
switch e := event.(type) {
|
switch e := event.(type) {
|
||||||
case *tcell.EventResize:
|
case *tcell.EventResize:
|
||||||
w, h := screen.Screen.Size()
|
t.Resize()
|
||||||
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()
|
|
||||||
}
|
|
||||||
case *tcell.EventMouse:
|
case *tcell.EventMouse:
|
||||||
mx, my := e.Position()
|
mx, my := e.Position()
|
||||||
switch e.Buttons() {
|
switch e.Buttons() {
|
||||||
case tcell.Button1:
|
case tcell.Button1:
|
||||||
ind := t.GetMouseLoc(buffer.Loc{mx, my})
|
ind := t.GetMouseLoc(buffer.Loc{mx, my})
|
||||||
if ind != -1 {
|
if ind != -1 {
|
||||||
t.Active = ind
|
t.SetActive(ind)
|
||||||
}
|
}
|
||||||
case tcell.WheelUp:
|
case tcell.WheelUp:
|
||||||
if my == t.Y {
|
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() {
|
func (t *TabList) Display() {
|
||||||
|
t.UpdateNames()
|
||||||
if len(t.List) > 1 {
|
if len(t.List) > 1 {
|
||||||
t.TabWindow.Display()
|
t.TabWindow.Display()
|
||||||
}
|
}
|
||||||
@@ -88,7 +119,7 @@ func InitTabs(bufs []*buffer.Buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func MainTab() *TabPane {
|
func MainTab() *TabPane {
|
||||||
return Tabs.List[Tabs.Active]
|
return Tabs.List[Tabs.Active()]
|
||||||
}
|
}
|
||||||
|
|
||||||
// A TabPane represents a single tab
|
// 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
|
// Remove pane removes the pane with the given index
|
||||||
func (t *TabPane) RemovePane(i int) {
|
func (t *TabPane) RemovePane(i int) {
|
||||||
copy(t.Panes[i:], t.Panes[i+1:])
|
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]
|
t.Panes = t.Panes[:len(t.Panes)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
type TabWindow struct {
|
type TabWindow struct {
|
||||||
Names []string
|
Names []string
|
||||||
Active int
|
active int
|
||||||
Y int
|
Y int
|
||||||
width int
|
width int
|
||||||
hscroll int
|
hscroll int
|
||||||
@@ -55,6 +55,28 @@ func (w *TabWindow) TotalSize() int {
|
|||||||
return sum - 4
|
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
|
// TODO: handle files with character width >=2
|
||||||
|
|
||||||
func (w *TabWindow) Display() {
|
func (w *TabWindow) Display() {
|
||||||
@@ -77,7 +99,7 @@ func (w *TabWindow) Display() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i, n := range w.Names {
|
for i, n := range w.Names {
|
||||||
if i == w.Active {
|
if i == w.active {
|
||||||
draw('[', 1)
|
draw('[', 1)
|
||||||
} else {
|
} else {
|
||||||
draw(' ', 1)
|
draw(' ', 1)
|
||||||
@@ -88,7 +110,7 @@ func (w *TabWindow) Display() {
|
|||||||
if i == len(w.Names)-1 {
|
if i == len(w.Names)-1 {
|
||||||
done = true
|
done = true
|
||||||
}
|
}
|
||||||
if i == w.Active {
|
if i == w.active {
|
||||||
draw(']', 1)
|
draw(']', 1)
|
||||||
draw(' ', 2)
|
draw(' ', 2)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user