306 lines
6.0 KiB
Go
306 lines
6.0 KiB
Go
package main
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
"unicode"
|
|
|
|
"github.com/gdamore/tcell/v2"
|
|
)
|
|
|
|
var (
|
|
pos int = 0
|
|
)
|
|
|
|
func drawTextLine(screen tcell.Screen, x, y int, s string, style tcell.Style) {
|
|
for _, r := range s {
|
|
screen.SetContent(x, y, r, nil, style)
|
|
x++
|
|
}
|
|
}
|
|
|
|
func drawLine(screen tcell.Screen, x, y, w int, style tcell.Style) {
|
|
for i := 0; i < w; i++ {
|
|
screen.SetContent(x, y, ' ', nil, style)
|
|
x++
|
|
}
|
|
}
|
|
|
|
func getNameSize(i Item, w int) (string, string) {
|
|
name := ""
|
|
size := ""
|
|
c := w / 2
|
|
if i.isDir {
|
|
name = "/" + filepath.Base(i.dir.path)
|
|
size = alignRight(6, sizeConv(i.dir.size))
|
|
} else {
|
|
name = i.file.name
|
|
size = alignRight(6, sizeConv(i.file.size))
|
|
}
|
|
if len(name) > c-14 && w > 60 {
|
|
name = name[:c-14] + "..."
|
|
} else if len(name) > w-14 {
|
|
name = name[:w-14] + "..."
|
|
}
|
|
|
|
return name, size
|
|
}
|
|
|
|
func (d Dir) draw(screen tcell.Screen, items []Item) {
|
|
title := "rdu - another disk usage utility"
|
|
mainStyle := tcell.StyleDefault.Foreground(tcell.NewHexColor(0xFFFFFF))
|
|
titleStyle := tcell.StyleDefault.Foreground(tcell.NewHexColor(0x000000)).Background(tcell.NewHexColor(0xFFFFFF)).Bold(true)
|
|
footStyle := tcell.StyleDefault.Foreground(tcell.NewHexColor(0x000000)).Background(tcell.NewHexColor(0xFFFFFF))
|
|
infoStyle := mainStyle.Foreground(tcell.NewHexColor(0xF012BE)).Bold(true)
|
|
|
|
screen.Fill(' ', mainStyle)
|
|
|
|
w, h := screen.Size()
|
|
c := w / 2
|
|
i := 0
|
|
if pos > h-4 {
|
|
i += pos - (h - 4)
|
|
}
|
|
l := 1
|
|
|
|
drawLine(screen, 0, 0, w, titleStyle)
|
|
drawTextLine(screen, c-len(title)/2, 0, title, titleStyle)
|
|
drawLine(screen, 0, h-1, w, footStyle)
|
|
drawTextLine(screen, 1, h-1, "Current directory size:", titleStyle)
|
|
drawTextLine(screen, 25, h-1, sizeConv(d.size), footStyle)
|
|
drawTextLine(screen, c+1, h-1, "Total scanned files:", titleStyle)
|
|
drawTextLine(screen, c+22, h-1, itoa(count), footStyle)
|
|
|
|
drawTextLine(screen, w-6, h-1, time.Now().Format("15:04"), footStyle)
|
|
|
|
path := d.path
|
|
for len(path) > c-6 {
|
|
tmp := strings.Split(path, "/")
|
|
tmp = tmp[1:]
|
|
path = strings.Join(tmp, "/")
|
|
if path == "" {
|
|
path = "/"
|
|
}
|
|
}
|
|
if len(d.path) > c-6 {
|
|
path = ".../" + path
|
|
}
|
|
drawTextLine(screen, c/2-len(path)/2, 1, path, mainStyle.Bold(true))
|
|
l++
|
|
|
|
for i < len(items) {
|
|
style := mainStyle
|
|
if i == pos {
|
|
style = infoStyle
|
|
if items[i].isDir && w > 60 {
|
|
next := getItems(*items[i].dir)
|
|
if next == nil {
|
|
continue
|
|
}
|
|
next = sortItems(next)
|
|
for j := 0; j < len(next); j++ {
|
|
if next[j].isDir {
|
|
name, size := getNameSize(next[j], w)
|
|
drawTextLine(screen, c+1, j+2, size, mainStyle)
|
|
drawTextLine(screen, c+10, j+2, name, mainStyle)
|
|
} else {
|
|
name, size := getNameSize(next[j], w)
|
|
drawTextLine(screen, c+1, j+2, size, mainStyle)
|
|
drawTextLine(screen, c+10, j+2, name, mainStyle)
|
|
}
|
|
if j >= h-4 {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if items[i].file != nil || items[i].dir != nil {
|
|
if items[i].isDir {
|
|
name, size := getNameSize(items[i], w)
|
|
drawTextLine(screen, 0, l, size, style)
|
|
drawTextLine(screen, 10, l, name, style)
|
|
} else {
|
|
name, size := getNameSize(items[i], w)
|
|
drawTextLine(screen, 0, l, size, style)
|
|
drawTextLine(screen, 10, l, name, style)
|
|
}
|
|
i++
|
|
l++
|
|
}
|
|
if l >= h-1 {
|
|
break
|
|
}
|
|
}
|
|
for i := 1; i < h-1; i++ {
|
|
drawTextLine(screen, c, i, "|", mainStyle)
|
|
}
|
|
}
|
|
|
|
func (d Dir) handle(event tcell.Event, items []Item) string {
|
|
switch event := event.(type) {
|
|
case *tcell.EventKey:
|
|
if event.Key() == tcell.KeyLeft || event.Key() == tcell.KeyEscape {
|
|
if d.prev != nil {
|
|
return "prev"
|
|
}
|
|
return ""
|
|
}
|
|
|
|
if event.Key() == tcell.KeyRight || event.Key() == tcell.KeyEnter {
|
|
if items == nil {
|
|
return ""
|
|
}
|
|
if !items[pos].isDir {
|
|
return ""
|
|
}
|
|
return "next"
|
|
}
|
|
|
|
if event.Key() == tcell.KeyUp {
|
|
pos -= 1
|
|
if pos < 0 {
|
|
pos = len(items) - 1
|
|
}
|
|
return "up"
|
|
}
|
|
|
|
if event.Key() == tcell.KeyDown {
|
|
pos += 1
|
|
if pos >= len(items) {
|
|
pos = 0
|
|
}
|
|
return "down"
|
|
}
|
|
|
|
if event.Key() == tcell.KeyPgUp {
|
|
pos -= 10
|
|
if pos < 0 {
|
|
pos = 0
|
|
}
|
|
return "up"
|
|
}
|
|
|
|
if event.Key() == tcell.KeyPgDn {
|
|
pos += 10
|
|
if pos >= len(items) {
|
|
pos = len(items) - 1
|
|
}
|
|
return "down"
|
|
}
|
|
|
|
if event.Key() == tcell.KeyCtrlC {
|
|
return "quit"
|
|
}
|
|
|
|
if event.Key() == tcell.KeyHome {
|
|
pos = 0
|
|
return "up"
|
|
}
|
|
|
|
if event.Key() == tcell.KeyEnd {
|
|
pos = len(items) - 1
|
|
return "down"
|
|
}
|
|
|
|
if event.Key() != tcell.KeyRune {
|
|
return ""
|
|
}
|
|
|
|
switch unicode.ToLower(event.Rune()) {
|
|
case 'q':
|
|
return "quit"
|
|
case 'r':
|
|
return "refresh"
|
|
case 'h':
|
|
return "help"
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func show(d Dir) {
|
|
screen, err := tcell.NewScreen()
|
|
if err != nil {
|
|
printerr(err)
|
|
os.Exit(1)
|
|
}
|
|
err = screen.Init()
|
|
if err != nil {
|
|
printerr(err)
|
|
os.Exit(1)
|
|
}
|
|
defer screen.Fini()
|
|
|
|
events := make(chan tcell.Event)
|
|
go func() {
|
|
for {
|
|
events <- screen.PollEvent()
|
|
time.Sleep(time.Millisecond * 20)
|
|
if screen.HasPendingEvent() {
|
|
screen.PollEvent()
|
|
}
|
|
}
|
|
}()
|
|
|
|
curr := &d
|
|
items := sortItems(getItems(*curr))
|
|
|
|
screen.Clear()
|
|
curr.draw(screen, items)
|
|
screen.Show()
|
|
|
|
refresh := time.Tick(time.Second * 10)
|
|
|
|
for {
|
|
select {
|
|
case event := <-events:
|
|
switch event := event.(type) {
|
|
case *tcell.EventResize:
|
|
screen.Clear()
|
|
curr.draw(screen, items)
|
|
screen.Sync()
|
|
default:
|
|
action := curr.handle(event, items)
|
|
if action == "quit" {
|
|
screen.Fini()
|
|
return
|
|
}
|
|
|
|
if action == "prev" {
|
|
items = sortItems(getItems(*curr.prev))
|
|
pos = getPos(curr.path, items)
|
|
curr = curr.prev
|
|
screen.Clear()
|
|
curr.draw(screen, items)
|
|
screen.Show()
|
|
continue
|
|
}
|
|
|
|
if action == "next" {
|
|
items[pos].dir.prev = curr
|
|
curr = items[pos].dir
|
|
pos = 0
|
|
items = sortItems(getItems(*curr))
|
|
screen.Clear()
|
|
curr.draw(screen, items)
|
|
screen.Show()
|
|
continue
|
|
}
|
|
|
|
if action != "" {
|
|
screen.Clear()
|
|
curr.draw(screen, items)
|
|
screen.Show()
|
|
}
|
|
}
|
|
case <-refresh:
|
|
screen.Clear()
|
|
curr.draw(screen, items)
|
|
screen.Show()
|
|
}
|
|
}
|
|
}
|