LSCOLORS & LS_COLORS support (#96)
* LSCOLORS & LS_COLORS support * Renamed lsColors to gColors * Fixed gOptWords & setExpr.eval()
This commit is contained in:
parent
54dbf5cbe4
commit
f92e0f53a5
3
comp.go
3
comp.go
@ -67,6 +67,9 @@ var (
|
||||
"ignorecase",
|
||||
"noignorecase",
|
||||
"ignorecase!",
|
||||
"lscolors",
|
||||
"nolscolors",
|
||||
"lscolors!",
|
||||
"preview",
|
||||
"nopreview",
|
||||
"preview!",
|
||||
|
1
doc.go
1
doc.go
@ -79,6 +79,7 @@ The following options can be used to customize the behavior of lf:
|
||||
globsearch boolean (default off)
|
||||
hidden boolean (default off)
|
||||
ignorecase boolean (default on)
|
||||
lscolors boolean (default on if LSCOLORS or LS_COLORS environment variable is set)
|
||||
preview boolean (default on)
|
||||
reverse boolean (default off)
|
||||
smartcase boolean (default on)
|
||||
|
@ -83,6 +83,7 @@ The following options can be used to customize the behavior of lf:
|
||||
globsearch boolean (default off)
|
||||
hidden boolean (default off)
|
||||
ignorecase boolean (default on)
|
||||
lscolors boolean (default on if LSCOLORS or LS_COLORS environment variable is set)
|
||||
preview boolean (default on)
|
||||
reverse boolean (default off)
|
||||
smartcase boolean (default on)
|
||||
|
6
eval.go
6
eval.go
@ -47,6 +47,12 @@ func (e *setExpr) eval(app *app, args []string) {
|
||||
gOpts.ignorecase = false
|
||||
case "ignorecase!":
|
||||
gOpts.ignorecase = !gOpts.ignorecase
|
||||
case "lscolors":
|
||||
gOpts.lscolors = true
|
||||
case "nolscolors":
|
||||
gOpts.lscolors = false
|
||||
case "lscolors!":
|
||||
gOpts.lscolors = !gOpts.lscolors
|
||||
case "preview":
|
||||
gOpts.preview = true
|
||||
case "nopreview":
|
||||
|
148
lscolors.go
Normal file
148
lscolors.go
Normal file
@ -0,0 +1,148 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/nsf/termbox-go"
|
||||
)
|
||||
|
||||
func init() {
|
||||
if lscolors := os.Getenv("LSCOLORS"); lscolors != "" {
|
||||
gColors.parseBSD(lscolors)
|
||||
gOpts.lscolors = true
|
||||
}
|
||||
if ls_colors := os.Getenv("LS_COLORS"); ls_colors != "" {
|
||||
gColors.parseLinux(ls_colors)
|
||||
gOpts.lscolors = true
|
||||
}
|
||||
}
|
||||
|
||||
type lsColorsEntry struct {
|
||||
fg termbox.Attribute
|
||||
bg termbox.Attribute
|
||||
}
|
||||
|
||||
type lsColorsT map[string]lsColorsEntry
|
||||
|
||||
var gColors = make(lsColorsT)
|
||||
|
||||
// This function parses LS_COLORS environment variable
|
||||
func (lsc lsColorsT) parseLinux(env string) {
|
||||
e := strings.Split(env, ":")
|
||||
for _, e := range e {
|
||||
i := strings.IndexRune(e, '=')
|
||||
if i >= 0 {
|
||||
key := e[:i]
|
||||
values := strings.Split(e[i+1:], ";")
|
||||
var fg, bg termbox.Attribute
|
||||
for _, a := range values {
|
||||
i, _ := strconv.Atoi(a) // strconv.Atoi() will returns 0 on error which is termbox.ColorDefault. No need to check the error.
|
||||
|
||||
switch {
|
||||
case i == 1:
|
||||
fg = fg | termbox.AttrBold
|
||||
case i == 4:
|
||||
fg = fg | termbox.AttrUnderline
|
||||
case i == 5:
|
||||
// Flashing text
|
||||
case i == 7:
|
||||
fg = fg | termbox.AttrReverse
|
||||
case i == 8:
|
||||
// Concealed
|
||||
case 30 <= i && i <= 37:
|
||||
fg = fg | termbox.Attribute(i-29)
|
||||
case 40 <= i && i <= 47:
|
||||
bg = bg | termbox.Attribute(i-39)
|
||||
}
|
||||
}
|
||||
lsc[key] = lsColorsEntry{fg: fg, bg: bg}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This function parses LSCOLORS variable. See http://www.manpages.info/freebsd/ls.1.html
|
||||
func (lsc lsColorsT) parseBSD(env string) {
|
||||
if len(env) != 22 {
|
||||
log.Print("LSCOLORS variable invalid")
|
||||
return
|
||||
}
|
||||
|
||||
unixLsColors := []string{"di", "so", "ln", "pi", "ex", "bd", "cd", "su", "sg", "tw", "ow"}
|
||||
unixColors := map[byte]termbox.Attribute{
|
||||
'a': termbox.ColorBlack,
|
||||
'b': termbox.ColorRed,
|
||||
'c': termbox.ColorGreen,
|
||||
'd': termbox.ColorYellow, // should be brown
|
||||
'e': termbox.ColorBlue,
|
||||
'f': termbox.ColorMagenta,
|
||||
'g': termbox.ColorCyan,
|
||||
'h': termbox.ColorWhite, // should be light grey
|
||||
'A': termbox.AttrBold | termbox.ColorBlack,
|
||||
'B': termbox.AttrBold | termbox.ColorRed,
|
||||
'C': termbox.AttrBold | termbox.ColorGreen,
|
||||
'D': termbox.AttrBold | termbox.ColorWhite, // brown
|
||||
'E': termbox.AttrBold | termbox.ColorBlue,
|
||||
'F': termbox.AttrBold | termbox.ColorMagenta,
|
||||
'G': termbox.AttrBold | termbox.ColorCyan,
|
||||
'H': termbox.AttrBold | termbox.ColorWhite, // light grey
|
||||
}
|
||||
|
||||
getColor := func(r byte) termbox.Attribute {
|
||||
if color, ok := unixColors[r]; ok {
|
||||
return color
|
||||
} else {
|
||||
return termbox.ColorDefault
|
||||
}
|
||||
}
|
||||
|
||||
for i, key := range unixLsColors {
|
||||
lsc[key] = lsColorsEntry{fg: getColor(env[i*2]), bg: getColor(env[i*2+1])}
|
||||
}
|
||||
}
|
||||
|
||||
// This function returns foreground and background colors for given file
|
||||
func (lsc lsColorsT) getColors(f *file) (termbox.Attribute, termbox.Attribute) {
|
||||
var key = ""
|
||||
|
||||
switch {
|
||||
case f.Mode()&os.ModeSticky != 0:
|
||||
key = "st"
|
||||
case f.Mode()&os.ModeSetuid != 0:
|
||||
key = "su"
|
||||
case f.Mode()&os.ModeSetgid != 0:
|
||||
key = "sg"
|
||||
case f.IsDir():
|
||||
key = "di"
|
||||
case f.linkState == working:
|
||||
key = "ln"
|
||||
case f.Mode()&os.ModeNamedPipe != 0:
|
||||
key = "pi"
|
||||
case f.Mode()&os.ModeSocket != 0:
|
||||
key = "so"
|
||||
case f.Mode()&os.ModeCharDevice != 0:
|
||||
key = "cd"
|
||||
case f.Mode()&os.ModeDevice != 0:
|
||||
key = "bd"
|
||||
case f.linkState == broken:
|
||||
key = "or"
|
||||
case f.Mode().IsRegular() && f.Mode()&0111 != 0:
|
||||
key = "ex"
|
||||
default:
|
||||
if extI := strings.LastIndexByte(f.Name(), '.'); extI > 0 {
|
||||
key = "*" + f.Name()[extI:]
|
||||
}
|
||||
}
|
||||
|
||||
if val, ok := lsc[key]; ok {
|
||||
return val.fg, val.bg
|
||||
} else {
|
||||
if val, ok = lsc["no"]; ok {
|
||||
return val.fg, val.bg
|
||||
} else {
|
||||
return termbox.ColorDefault, termbox.ColorDefault
|
||||
}
|
||||
}
|
||||
}
|
2
opts.go
2
opts.go
@ -8,6 +8,7 @@ var gOpts struct {
|
||||
globsearch bool
|
||||
hidden bool
|
||||
ignorecase bool
|
||||
lscolors bool
|
||||
preview bool
|
||||
reverse bool
|
||||
smartcase bool
|
||||
@ -34,6 +35,7 @@ func init() {
|
||||
gOpts.globsearch = false
|
||||
gOpts.hidden = false
|
||||
gOpts.ignorecase = true
|
||||
// gOpts.lscolors = true this option is initialized in lscolors.go init() depending on whether the corresponding environment variable is set
|
||||
gOpts.preview = true
|
||||
gOpts.reverse = false
|
||||
gOpts.smartcase = true
|
||||
|
46
ui.go
46
ui.go
@ -296,28 +296,32 @@ func (win *win) printDir(dir *dir, marks map[string]int, saves map[string]bool)
|
||||
end := min(beg+win.h, maxind+1)
|
||||
|
||||
for i, f := range dir.fi[beg:end] {
|
||||
switch {
|
||||
case f.linkState == working:
|
||||
fg = termbox.ColorCyan
|
||||
if f.Mode().IsDir() {
|
||||
fg |= termbox.AttrBold
|
||||
if gOpts.lscolors {
|
||||
fg, bg = gColors.getColors(f)
|
||||
} else {
|
||||
switch {
|
||||
case f.linkState == working:
|
||||
fg = termbox.ColorCyan
|
||||
if f.Mode().IsDir() {
|
||||
fg |= termbox.AttrBold
|
||||
}
|
||||
case f.linkState == broken:
|
||||
fg = termbox.ColorMagenta
|
||||
case f.Mode().IsRegular():
|
||||
if f.Mode()&0111 != 0 {
|
||||
fg = termbox.AttrBold | termbox.ColorGreen
|
||||
} else {
|
||||
fg = termbox.ColorDefault
|
||||
}
|
||||
case f.Mode().IsDir():
|
||||
fg = termbox.AttrBold | termbox.ColorBlue
|
||||
case f.Mode()&os.ModeNamedPipe != 0:
|
||||
fg = termbox.ColorRed
|
||||
case f.Mode()&os.ModeSocket != 0:
|
||||
fg = termbox.ColorYellow
|
||||
case f.Mode()&os.ModeDevice != 0:
|
||||
fg = termbox.ColorWhite
|
||||
}
|
||||
case f.linkState == broken:
|
||||
fg = termbox.ColorMagenta
|
||||
case f.Mode().IsRegular():
|
||||
if f.Mode()&0111 != 0 {
|
||||
fg = termbox.AttrBold | termbox.ColorGreen
|
||||
} else {
|
||||
fg = termbox.ColorDefault
|
||||
}
|
||||
case f.Mode().IsDir():
|
||||
fg = termbox.AttrBold | termbox.ColorBlue
|
||||
case f.Mode()&os.ModeNamedPipe != 0:
|
||||
fg = termbox.ColorRed
|
||||
case f.Mode()&os.ModeSocket != 0:
|
||||
fg = termbox.ColorYellow
|
||||
case f.Mode()&os.ModeDevice != 0:
|
||||
fg = termbox.ColorWhite
|
||||
}
|
||||
|
||||
path := filepath.Join(dir.path, f.Name())
|
||||
|
Loading…
Reference in New Issue
Block a user