add colors/icons file support

cc #505
This commit is contained in:
Gokcehan 2022-02-13 16:58:53 +03:00
parent 375133e483
commit 17453f10f5
8 changed files with 210 additions and 14 deletions

View File

@ -72,6 +72,12 @@ func parseStyles() styleMap {
sm.parseGNU(env) sm.parseGNU(env)
} }
for _, path := range gColorsPaths {
if _, err := os.Stat(path); !os.IsNotExist(err) {
sm.parseFile(path)
}
}
return sm return sm
} }
@ -158,6 +164,35 @@ func applyAnsiCodes(s string, st tcell.Style) tcell.Style {
return st return st
} }
func (sm styleMap) parseFile(path string) {
log.Printf("reading file: %s", path)
f, err := os.Open(path)
if err != nil {
log.Printf("opening colors file: %s", err)
return
}
defer f.Close()
pairs, err := readPairs(f)
if err != nil {
log.Printf("reading colors file: %s", err)
return
}
for _, pair := range pairs {
key, val := pair[0], pair[1]
key = replaceTilde(key)
if filepath.IsAbs(key) {
key = filepath.Clean(key)
}
sm[key] = applyAnsiCodes(val, tcell.StyleDefault)
}
}
// This function parses $LS_COLORS environment variable. // This function parses $LS_COLORS environment variable.
func (sm styleMap) parseGNU(env string) { func (sm styleMap) parseGNU(env string) {
for _, entry := range strings.Split(env, ":") { for _, entry := range strings.Split(env, ":") {

20
doc.go
View File

@ -194,6 +194,16 @@ Configuration files should be located at:
unix /etc/lf/lfrc ~/.config/lf/lfrc unix /etc/lf/lfrc ~/.config/lf/lfrc
windows C:\ProgramData\lf\lfrc C:\Users\<user>\AppData\Local\lf\lfrc windows C:\ProgramData\lf\lfrc C:\Users\<user>\AppData\Local\lf\lfrc
Colors file should be located at:
unix ~/.local/share/lf/colors
windows C:\Users\<user>\AppData\Local\lf\colors
Icons file should be located at:
unix ~/.local/share/lf/icons
windows C:\Users\<user>\AppData\Local\lf\icons
Selection file should be located at: Selection file should be located at:
unix ~/.local/share/lf/files unix ~/.local/share/lf/files
@ -1297,17 +1307,20 @@ Colors are set in the following order:
2. LSCOLORS (Mac/BSD ls) 2. LSCOLORS (Mac/BSD ls)
3. LS_COLORS (GNU ls) 3. LS_COLORS (GNU ls)
4. LF_COLORS (lf specific) 4. LF_COLORS (lf specific)
5. colors file (lf specific)
Please refer to the corresponding man pages for more information about 'LSCOLORS' and 'LS_COLORS'. Please refer to the corresponding man pages for more information about 'LSCOLORS' and 'LS_COLORS'.
'LF_COLORS' is provided with the same syntax as 'LS_COLORS' in case you want to configure colors only for lf but not ls. 'LF_COLORS' is provided with the same syntax as 'LS_COLORS' in case you want to configure colors only for lf but not ls.
This can be useful since there are some differences between ls and lf, though one should expect the same behavior for common cases. This can be useful since there are some differences between ls and lf, though one should expect the same behavior for common cases.
Colors file is provided for easier configuration without environment variables.
This file should consist of whitespace separated pairs with '#' character to start comments until the end of line.
You can configure lf colors in two different ways. You can configure lf colors in two different ways.
First, you can only configure 8 basic colors used by your terminal and lf should pick up those colors automatically. First, you can only configure 8 basic colors used by your terminal and lf should pick up those colors automatically.
Depending on your terminal, you should be able to select your colors from a 24-bit palette. Depending on your terminal, you should be able to select your colors from a 24-bit palette.
This is the recommended approach as colors used by other programs will also match each other. This is the recommended approach as colors used by other programs will also match each other.
Second, you can set the values of environmental variables mentioned above for fine grained customization. Second, you can set the values of environment variables mentioned above for fine grained customization.
Note that 'LS_COLORS/LF_COLORS' are more powerful than 'LSCOLORS' and they can be used even when GNU programs are not installed on the system. Note that 'LS_COLORS/LF_COLORS' are more powerful than 'LSCOLORS' and they can be used even when GNU programs are not installed on the system.
You can combine this second method with the first method for best results. You can combine this second method with the first method for best results.
@ -1409,9 +1422,10 @@ https://en.wikipedia.org/wiki/ANSI_escape_code.
Icons Icons
Icons are configured using 'LF_ICONS' environment variable. Icons are configured using 'LF_ICONS' environment variable or an icons file.
This variable uses the same syntax as 'LS_COLORS/LF_COLORS'. The variable uses the same syntax as 'LS_COLORS/LF_COLORS'.
Instead of colors, you should put a single characters as values of entries. Instead of colors, you should put a single characters as values of entries.
Icons file should consist of whitespace separated pairs with '#' character to start comments until the end of line.
Do not forget to enable 'icons' option to see the icons. Do not forget to enable 'icons' option to see the icons.
Default values are as follows given with their matching order in lf: Default values are as follows given with their matching order in lf:

View File

@ -199,6 +199,16 @@ Configuration files should be located at:
unix /etc/lf/lfrc ~/.config/lf/lfrc unix /etc/lf/lfrc ~/.config/lf/lfrc
windows C:\ProgramData\lf\lfrc C:\Users\<user>\AppData\Local\lf\lfrc windows C:\ProgramData\lf\lfrc C:\Users\<user>\AppData\Local\lf\lfrc
Colors file should be located at:
unix ~/.local/share/lf/colors
windows C:\Users\<user>\AppData\Local\lf\colors
Icons file should be located at:
unix ~/.local/share/lf/icons
windows C:\Users\<user>\AppData\Local\lf\icons
Selection file should be located at: Selection file should be located at:
unix ~/.local/share/lf/files unix ~/.local/share/lf/files
@ -1457,12 +1467,16 @@ are set in the following order:
2. LSCOLORS (Mac/BSD ls) 2. LSCOLORS (Mac/BSD ls)
3. LS_COLORS (GNU ls) 3. LS_COLORS (GNU ls)
4. LF_COLORS (lf specific) 4. LF_COLORS (lf specific)
5. colors file (lf specific)
Please refer to the corresponding man pages for more information about Please refer to the corresponding man pages for more information about
'LSCOLORS' and 'LS_COLORS'. 'LF_COLORS' is provided with the same syntax as 'LSCOLORS' and 'LS_COLORS'. 'LF_COLORS' is provided with the same syntax as
'LS_COLORS' in case you want to configure colors only for lf but not ls. 'LS_COLORS' in case you want to configure colors only for lf but not ls.
This can be useful since there are some differences between ls and lf, This can be useful since there are some differences between ls and lf,
though one should expect the same behavior for common cases. though one should expect the same behavior for common cases. Colors file is
provided for easier configuration without environment variables. This file
should consist of whitespace separated pairs with '#' character to start
comments until the end of line.
You can configure lf colors in two different ways. First, you can only You can configure lf colors in two different ways. First, you can only
configure 8 basic colors used by your terminal and lf should pick up those configure 8 basic colors used by your terminal and lf should pick up those
@ -1470,8 +1484,8 @@ colors automatically. Depending on your terminal, you should be able to
select your colors from a 24-bit palette. This is the recommended approach select your colors from a 24-bit palette. This is the recommended approach
as colors used by other programs will also match each other. as colors used by other programs will also match each other.
Second, you can set the values of environmental variables mentioned above Second, you can set the values of environment variables mentioned above for
for fine grained customization. Note that 'LS_COLORS/LF_COLORS' are more fine grained customization. Note that 'LS_COLORS/LF_COLORS' are more
powerful than 'LSCOLORS' and they can be used even when GNU programs are not powerful than 'LSCOLORS' and they can be used even when GNU programs are not
installed on the system. You can combine this second method with the first installed on the system. You can combine this second method with the first
method for best results. method for best results.
@ -1589,11 +1603,13 @@ https://en.wikipedia.org/wiki/ANSI_escape_code.
Icons Icons
Icons are configured using 'LF_ICONS' environment variable. This variable Icons are configured using 'LF_ICONS' environment variable or an icons file.
uses the same syntax as 'LS_COLORS/LF_COLORS'. Instead of colors, you should The variable uses the same syntax as 'LS_COLORS/LF_COLORS'. Instead of
put a single characters as values of entries. Do not forget to enable colors, you should put a single characters as values of entries. Icons file
'icons' option to see the icons. Default values are as follows given with should consist of whitespace separated pairs with '#' character to start
their matching order in lf: comments until the end of line. Do not forget to enable 'icons' option to
see the icons. Default values are as follows given with their matching order
in lf:
ln 🗎 ln 🗎
or 🗎 or 🗎

View File

@ -35,9 +35,44 @@ func parseIcons() iconMap {
im.parseEnv(env) im.parseEnv(env)
} }
for _, path := range gIconsPaths {
if _, err := os.Stat(path); !os.IsNotExist(err) {
im.parseFile(path)
}
}
return im return im
} }
func (im iconMap) parseFile(path string) {
log.Printf("reading file: %s", path)
f, err := os.Open(path)
if err != nil {
log.Printf("opening icons file: %s", err)
return
}
defer f.Close()
pairs, err := readPairs(f)
if err != nil {
log.Printf("reading icons file: %s", err)
return
}
for _, pair := range pairs {
key, val := pair[0], pair[1]
key = replaceTilde(key)
if filepath.IsAbs(key) {
key = filepath.Clean(key)
}
im[key] = val
}
}
func (im iconMap) parseEnv(env string) { func (im iconMap) parseEnv(env string) {
for _, entry := range strings.Split(env, ":") { for _, entry := range strings.Split(env, ":") {
if entry == "" { if entry == "" {

21
lf.1
View File

@ -221,6 +221,20 @@ Configuration files should be located at:
windows C:\eProgramData\elf\elfrc C:\eUsers\e<user>\eAppData\eLocal\elf\elfrc windows C:\eProgramData\elf\elfrc C:\eUsers\e<user>\eAppData\eLocal\elf\elfrc
.EE .EE
.PP .PP
Colors file should be located at:
.PP
.EX
unix ~/.local/share/lf/colors
windows C:\eUsers\e<user>\eAppData\eLocal\elf\ecolors
.EE
.PP
Icons file should be located at:
.PP
.EX
unix ~/.local/share/lf/icons
windows C:\eUsers\e<user>\eAppData\eLocal\elf\eicons
.EE
.PP
Selection file should be located at: Selection file should be located at:
.PP .PP
.EX .EX
@ -1450,13 +1464,14 @@ lf tries to automatically adapt its colors to the environment. It starts with a
2. LSCOLORS (Mac/BSD ls) 2. LSCOLORS (Mac/BSD ls)
3. LS_COLORS (GNU ls) 3. LS_COLORS (GNU ls)
4. LF_COLORS (lf specific) 4. LF_COLORS (lf specific)
5. colors file (lf specific)
.EE .EE
.PP .PP
Please refer to the corresponding man pages for more information about 'LSCOLORS' and 'LS_COLORS'. 'LF_COLORS' is provided with the same syntax as 'LS_COLORS' in case you want to configure colors only for lf but not ls. This can be useful since there are some differences between ls and lf, though one should expect the same behavior for common cases. Please refer to the corresponding man pages for more information about 'LSCOLORS' and 'LS_COLORS'. 'LF_COLORS' is provided with the same syntax as 'LS_COLORS' in case you want to configure colors only for lf but not ls. This can be useful since there are some differences between ls and lf, though one should expect the same behavior for common cases. Colors file is provided for easier configuration without environment variables. This file should consist of whitespace separated pairs with '#' character to start comments until the end of line.
.PP .PP
You can configure lf colors in two different ways. First, you can only configure 8 basic colors used by your terminal and lf should pick up those colors automatically. Depending on your terminal, you should be able to select your colors from a 24-bit palette. This is the recommended approach as colors used by other programs will also match each other. You can configure lf colors in two different ways. First, you can only configure 8 basic colors used by your terminal and lf should pick up those colors automatically. Depending on your terminal, you should be able to select your colors from a 24-bit palette. This is the recommended approach as colors used by other programs will also match each other.
.PP .PP
Second, you can set the values of environmental variables mentioned above for fine grained customization. Note that 'LS_COLORS/LF_COLORS' are more powerful than 'LSCOLORS' and they can be used even when GNU programs are not installed on the system. You can combine this second method with the first method for best results. Second, you can set the values of environment variables mentioned above for fine grained customization. Note that 'LS_COLORS/LF_COLORS' are more powerful than 'LSCOLORS' and they can be used even when GNU programs are not installed on the system. You can combine this second method with the first method for best results.
.PP .PP
Lastly, you may also want to configure the colors of the prompt line to match the rest of the colors. Colors of the prompt line can be configured using the 'promptfmt' option which can include hardcoded colors as ansi escapes. See the default value of this option to have an idea about how to color this line. Lastly, you may also want to configure the colors of the prompt line to match the rest of the colors. Colors of the prompt line can be configured using the 'promptfmt' option which can include hardcoded colors as ansi escapes. See the default value of this option to have an idea about how to color this line.
.PP .PP
@ -1557,7 +1572,7 @@ Having such a long variable definition in a shell configuration file might be un
.PP .PP
See the wiki page for ansi escape codes https://en.wikipedia.org/wiki/ANSI_escape_code. See the wiki page for ansi escape codes https://en.wikipedia.org/wiki/ANSI_escape_code.
.SH ICONS .SH ICONS
Icons are configured using 'LF_ICONS' environment variable. This variable uses the same syntax as 'LS_COLORS/LF_COLORS'. Instead of colors, you should put a single characters as values of entries. Do not forget to enable 'icons' option to see the icons. Default values are as follows given with their matching order in lf: Icons are configured using 'LF_ICONS' environment variable or an icons file. The variable uses the same syntax as 'LS_COLORS/LF_COLORS'. Instead of colors, you should put a single characters as values of entries. Icons file should consist of whitespace separated pairs with '#' character to start comments until the end of line. Do not forget to enable 'icons' option to see the icons. Default values are as follows given with their matching order in lf:
.PP .PP
.EX .EX
ln 🗎 ln 🗎

57
misc.go
View File

@ -1,7 +1,10 @@
package main package main
import ( import (
"bufio"
"errors"
"fmt" "fmt"
"io"
"path/filepath" "path/filepath"
"regexp" "regexp"
"strconv" "strconv"
@ -133,6 +136,60 @@ func splitWord(s string) (word, rest string) {
return return
} }
var reComment = regexp.MustCompile(`#.*$`)
var reTrailingSpace = regexp.MustCompile(`\s+$`)
func readPairs(r io.Reader) ([][]string, error) {
var pairs [][]string
s := bufio.NewScanner(r)
for s.Scan() {
line := s.Text()
line = reComment.ReplaceAllString(line, "")
line = reTrailingSpace.ReplaceAllString(line, "")
if line == "" {
continue
}
squote, dquote := false, false
pair := strings.FieldsFunc(line, func(r rune) bool {
if r == '\'' && !dquote {
squote = !squote
} else if r == '"' && !squote {
dquote = !dquote
}
return !squote && !dquote && unicode.IsSpace(r)
})
if len(pair) != 2 {
return nil, errors.New(fmt.Sprintf("expected pair but found: %s", s.Text()))
continue
}
for i := 0; i < len(pair); i++ {
squote, dquote := false, false
buf := make([]rune, 0, len(pair[i]))
for _, r := range pair[i] {
if r == '\'' && !dquote {
squote = !squote
continue
}
if r == '"' && !squote {
dquote = !dquote
continue
}
buf = append(buf, r)
}
pair[i] = string(buf)
}
pairs = append(pairs, pair)
}
return pairs, nil
}
// This function converts a size in bytes to a human readable form using metric // This function converts a size in bytes to a human readable form using metric
// suffixes (e.g. 1K = 1000). For values less than 10 the first significant // suffixes (e.g. 1K = 1000). For values less than 10 the first significant
// digit is shown, otherwise it is hidden. Numbers are always rounded down. // digit is shown, otherwise it is hidden. Numbers are always rounded down.

12
os.go
View File

@ -31,6 +31,8 @@ var (
var ( var (
gUser *user.User gUser *user.User
gConfigPaths []string gConfigPaths []string
gColorsPaths []string
gIconsPaths []string
gFilesPath string gFilesPath string
gMarksPath string gMarksPath string
gHistoryPath string gHistoryPath string
@ -79,6 +81,16 @@ func init() {
filepath.Join(config, "lf", "lfrc"), filepath.Join(config, "lf", "lfrc"),
} }
gColorsPaths = []string{
filepath.Join("/etc", "lf", "colors"),
filepath.Join(config, "lf", "colors"),
}
gIconsPaths = []string{
filepath.Join("/etc", "lf", "icons"),
filepath.Join(config, "lf", "icons"),
}
data := os.Getenv("XDG_DATA_HOME") data := os.Getenv("XDG_DATA_HOME")
if data == "" { if data == "" {
data = filepath.Join(gUser.HomeDir, ".local", "share") data = filepath.Join(gUser.HomeDir, ".local", "share")

View File

@ -30,6 +30,8 @@ var (
var ( var (
gUser *user.User gUser *user.User
gConfigPaths []string gConfigPaths []string
gColorsPaths []string
gIconsPaths []string
gFilesPath string gFilesPath string
gMarksPath string gMarksPath string
gHistoryPath string gHistoryPath string
@ -68,6 +70,16 @@ func init() {
filepath.Join(data, "lf", "lfrc"), filepath.Join(data, "lf", "lfrc"),
} }
gColorsPaths = []string{
filepath.Join(os.Getenv("ProgramData"), "lf", "colors"),
filepath.Join(data, "lf", "colors"),
}
gIconsPaths = []string{
filepath.Join(os.Getenv("ProgramData"), "lf", "icons"),
filepath.Join(data, "lf", "icons"),
}
gFilesPath = filepath.Join(data, "lf", "files") gFilesPath = filepath.Join(data, "lf", "files")
gMarksPath = filepath.Join(data, "lf", "marks") gMarksPath = filepath.Join(data, "lf", "marks")
gHistoryPath = filepath.Join(data, "lf", "history") gHistoryPath = filepath.Join(data, "lf", "history")