Skip to content

Commit

Permalink
Load the configured theme at startup
Browse files Browse the repository at this point in the history
Termshark will now look in termshark.toml for a main.theme key. If set
to e.g. foobar, then termshark will attempt to load (1)
~/.config/termshark/themes/foobar.toml, and failing that (2) see if it
has a built-in theme called /themes/foobar.toml via its statik
filesystem. If it finds the toml, regardless of the contents, the theme
will be active and called foobar. Then when loading its color palette,
any config-file references to colors e.g. dark.progress-bar - will look
up a key dark.progress bar in the toml loaded from foobar.toml. If,
eventually, a value is found that can be parsed as a color, termshark
will use it for that UI element.
  • Loading branch information
gcla committed Sep 11, 2020
1 parent b51a445 commit 2edf53d
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 19 deletions.
9 changes: 9 additions & 0 deletions cmd/termshark/termshark.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/gcla/termshark/v2/pcap"
"github.com/gcla/termshark/v2/streams"
"github.com/gcla/termshark/v2/system"
"github.com/gcla/termshark/v2/theme"
"github.com/gcla/termshark/v2/tty"
"github.com/gcla/termshark/v2/ui"
"github.com/gcla/termshark/v2/widgets/filter"
Expand Down Expand Up @@ -675,6 +676,14 @@ func cmain() int {
ui.AutoScroll = termshark.ConfBool("main.auto-scroll", true)
ui.PacketColors = termshark.ConfBool("main.packet-colors", true)

themeName := termshark.ConfString("main.theme", "")
if themeName != "" {
err = theme.Load(themeName)
if err != nil {
log.Warnf("Theme %s could not be loaded: %v", themeName, err)
}
}

// Set them up here so they have access to any command-line flags that
// need to be passed to the tshark commands used
pdmlArgs := termshark.ConfStringSlice("main.pdml-args", []string{})
Expand Down
87 changes: 69 additions & 18 deletions theme/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,17 @@
package theme

import (
"fmt"
"io"
"os"
"path/filepath"

"github.com/gcla/gowid"
"github.com/gcla/termshark/v2"
log "github.com/sirupsen/logrus"
"github.com/rakyll/statik/fs"
"github.com/shibukawa/configdir"
"github.com/spf13/viper"

_ "github.com/gcla/termshark/v2/assets/statik"
)

//======================================================================
Expand All @@ -20,39 +28,82 @@ const (
Background Layer = iota
)

var theme *viper.Viper

// MakeColorSafe extends gowid's MakeColorSafe function, prefering to interpret
// its string argument as a toml file config key lookup first; if this fails, then
// fall back to gowid.MakeColorSafe, which will then read colors as urwid color names,
// #-prefixed hex digits, grayscales, etc.
func MakeColorSafe(s string, l Layer) (gowid.Color, error) {
loops := 10
cur := s
for {
next := termshark.ConfString(cur, "")
if next != "" {
cur = next
} else {
next := termshark.ConfStringSlice(cur, []string{})
if len(next) != 2 {
break
if theme != nil {
for {
next := theme.GetString(cur)
if next != "" {
cur = next
} else {
cur = next[l]
next := theme.GetStringSlice(cur)
if next == nil || len(next) != 2 {
break
} else {
cur = next[l]
}
}
loops -= 1
if loops == 0 {
break
}
}
loops -= 1
if loops == 0 {
break
}
}
col, err := gowid.MakeColorSafe(cur)
if err == nil {
return gowid.Color{IColor: col, Id: s}, nil
}
col, err = gowid.MakeColorSafe(s)
return gowid.MakeColorSafe(s)
}

// Clear resets the package-level theme object. Next time ui.SetupColors is called,
// the theme-connected colors won't be found, and termshark will fall back to its
// programmed default colors.
func Clear() {
theme = nil
}

// Load will set the package-level theme object to a viper object representing the
// toml file either (a) read from disk, or failing that (b) built-in to termshark.
// Disk themes are prefered and take precedence.
func Load(name string) error {
theme = viper.New()
theme.SetConfigType("toml")
stdConf := configdir.New("", "termshark")
dirs := stdConf.QueryFolders(configdir.Global)

// Prefer to load from disk
themeFileName := filepath.Join(dirs[0].Path, "themes", fmt.Sprintf("%s.toml", name))

var file io.ReadCloser
var err error

file, err = os.Open(themeFileName)
if err == nil {
defer file.Close()
return theme.ReadConfig(file)
}

// Fall back to built-in themes
statikFS, err := fs.New()
if err != nil {
log.Infof("Could not understand configured theme color '%s'", s)
return err
}
return col, err

file, err = statikFS.Open(filepath.Join("/themes", fmt.Sprintf("%s.toml", name)))
if err != nil {
return err
}
defer file.Close()

return theme.ReadConfig(file)
}

//======================================================================
Expand Down
13 changes: 12 additions & 1 deletion ui/palette.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import (
"fmt"

"github.com/gcla/gowid"
"github.com/gcla/termshark/v2"
"github.com/gcla/termshark/v2/theme"
"github.com/gcla/termshark/v2/theme/modeswap"
log "github.com/sirupsen/logrus"
)

//======================================================================
Expand Down Expand Up @@ -280,10 +282,19 @@ func lbg(key string, fb gowid.IColor) gowid.IColor {
}

func tomlCol(key string, layer theme.Layer, hue string, fb gowid.IColor) gowid.IColor {
col, err := theme.MakeColorSafe(fmt.Sprintf("themes.rules.%s.%s", hue, key), layer)
rule := fmt.Sprintf("%s.%s", hue, key)
col, err := theme.MakeColorSafe(rule, layer)
if err == nil {
return col
} else {
// Warn if the user has defined themes.rules.etcetc, but the resulting
// color can't be resolved. If no key is present, it means the user hasn't
// set up themes, so ignore.
if termshark.ConfString("main.theme", "") != "" {
log.Infof("Could not understand configured theme color '%s'", key)
}
}

return fb
}

Expand Down

0 comments on commit 2edf53d

Please sign in to comment.