oh-my-posh/src/segment.go

321 lines
9.5 KiB
Go
Raw Normal View History

2019-03-13 04:14:30 -07:00
package main
import (
"errors"
"fmt"
"oh-my-posh/environment"
"oh-my-posh/properties"
"runtime/debug"
"time"
)
2020-09-17 07:51:29 -07:00
// Segment represent a single segment and it's configuration
2019-03-13 04:14:30 -07:00
type Segment struct {
Type SegmentType `config:"type"`
Tips []string `config:"tips"`
Style SegmentStyle `config:"style"`
PowerlineSymbol string `config:"powerline_symbol"`
InvertPowerline bool `config:"invert_powerline"`
Foreground string `config:"foreground"`
ForegroundTemplates []string `config:"foreground_templates"`
Background string `config:"background"`
BackgroundTemplates []string `config:"background_templates"`
LeadingDiamond string `config:"leading_diamond"`
TrailingDiamond string `config:"trailing_diamond"`
Properties properties.Map `config:"properties"`
writer SegmentWriter
stringValue string
active bool
env environment.Environment
2019-03-13 04:14:30 -07:00
}
// SegmentTiming holds the timing context for a segment
type SegmentTiming struct {
name string
nameLength int
enabled bool
stringValue string
enabledDuration time.Duration
stringDuration time.Duration
}
// SegmentWriter is the interface used to define what and if to write to the prompt
2019-03-13 04:14:30 -07:00
type SegmentWriter interface {
Enabled() bool
Template() string
Init(props properties.Properties, env environment.Environment)
2019-03-13 04:14:30 -07:00
}
// SegmentStyle the syle of segment, for more information, see the constants
2019-03-13 04:14:30 -07:00
type SegmentStyle string
// SegmentType the type of segment, for more information, see the constants
2019-03-13 04:14:30 -07:00
type SegmentType string
const (
2022-01-26 05:10:18 -08:00
// SESSION represents the user info segment
SESSION SegmentType = "session"
// PATH represents the current path segment
PATH SegmentType = "path"
// GIT represents the git status and information
GIT SegmentType = "git"
// PLASTIC represents the plastic scm status and information
PLASTIC SegmentType = "plastic"
// EXIT writes the last exit code
EXIT SegmentType = "exit"
// PYTHON writes the virtual env name
PYTHON SegmentType = "python"
// ROOT writes root symbol
ROOT SegmentType = "root"
// TIME writes the current timestamp
TIME SegmentType = "time"
// TEXT writes a text
TEXT SegmentType = "text"
// CMD writes the output of a shell command
CMD SegmentType = "command"
// BATTERY writes the battery percentage
BATTERY SegmentType = "battery"
// SPOTIFY writes the SPOTIFY status for Mac
SPOTIFY SegmentType = "spotify"
// SHELL writes which shell we're currently in
SHELL SegmentType = "shell"
// NODE writes which node version is currently active
NODE SegmentType = "node"
// OS write os specific icon
OS SegmentType = "os"
// AZ writes the Azure subscription info we're currently in
AZ SegmentType = "az"
// KUBECTL writes the Kubernetes context we're currently in
KUBECTL SegmentType = "kubectl"
// DOTNET writes which dotnet version is currently active
DOTNET SegmentType = "dotnet"
// TERRAFORM writes the terraform workspace we're currently in
TERRAFORM SegmentType = "terraform"
// GOLANG writes which go version is currently active
GOLANG SegmentType = "go"
// JULIA writes which julia version is currently active
JULIA SegmentType = "julia"
// Powerline writes it Powerline style
2019-03-13 04:14:30 -07:00
Powerline SegmentStyle = "powerline"
// Plain writes it without ornaments
2019-03-13 04:14:30 -07:00
Plain SegmentStyle = "plain"
// Diamond writes the prompt shaped with a leading and trailing symbol
2019-03-13 04:14:30 -07:00
Diamond SegmentStyle = "diamond"
// YTM writes YouTube Music information and status
YTM SegmentType = "ytm"
2022-01-26 05:10:18 -08:00
// EXECUTIONTIME writes the execution time of the last run command
EXECUTIONTIME SegmentType = "executiontime"
// RUBY writes which ruby version is currently active
RUBY SegmentType = "ruby"
// AWS writes the active aws context
AWS SegmentType = "aws"
// JAVA writes the active java version
JAVA SegmentType = "java"
// POSHGIT writes the posh git prompt
POSHGIT SegmentType = "poshgit"
// AZFUNC writes current AZ func version
AZFUNC SegmentType = "azfunc"
// CRYSTAL writes the active crystal version
CRYSTAL SegmentType = "crystal"
// DART writes the active dart version
DART SegmentType = "dart"
// NBGV writes the nbgv version information
NBGV SegmentType = "nbgv"
// RUST writes the cargo version information if cargo.toml is present
RUST SegmentType = "rust"
// OWM writes the weather coming from openweatherdata
OWM SegmentType = "owm"
2022-01-26 05:10:18 -08:00
// SYSTEMINFO writes system information (memory, cpu, load)
SYSTEMINFO SegmentType = "sysinfo"
// ANGULAR writes which angular cli version us currently active
ANGULAR SegmentType = "angular"
2021-10-27 01:52:56 -07:00
// PHP writes which php version is currently active
PHP SegmentType = "php"
2022-01-26 05:10:18 -08:00
// NIGHTSCOUT is an open source diabetes system
NIGHTSCOUT SegmentType = "nightscout"
// STRAVA is a sports activity tracker
STRAVA SegmentType = "strava"
// WAKATIME writes tracked time spend in dev editors
WAKATIME SegmentType = "wakatime"
// WIFI writes details about the current WIFI connection
WIFI SegmentType = "wifi"
// WINREG queries the Windows registry.
WINREG SegmentType = "winreg"
2021-12-14 23:49:32 -08:00
// Brewfather segment
2022-01-26 05:10:18 -08:00
BREWFATHER SegmentType = "brewfather"
// IPIFY segment
IPIFY SegmentType = "ipify"
2019-03-13 04:14:30 -07:00
)
func (segment *Segment) string() string {
template := &textTemplate{
Template: segment.writer.Template(),
Context: segment.writer,
Env: segment.env,
}
text, err := template.render()
if err != nil {
return err.Error()
}
return text
2019-03-13 04:14:30 -07:00
}
func (segment *Segment) enabled() bool {
segment.active = segment.writer.Enabled()
return segment.active
2019-03-13 04:14:30 -07:00
}
func (segment *Segment) getValue(property properties.Property, defaultValue string) string {
2020-10-02 07:58:25 -07:00
if value, ok := segment.Properties[property]; ok {
return properties.ParseString(value, defaultValue)
2020-10-02 07:58:25 -07:00
}
return defaultValue
}
func (segment *Segment) shouldIncludeFolder() bool {
cwdIncluded := segment.cwdIncluded()
cwdExcluded := segment.cwdExcluded()
2021-02-27 20:05:51 -08:00
return (cwdIncluded && !cwdExcluded)
}
func (segment *Segment) cwdIncluded() bool {
value, ok := segment.Properties[properties.IncludeFolders]
2021-02-27 20:05:51 -08:00
if !ok {
// IncludeFolders isn't specified, everything is included
return true
}
list := properties.ParseStringArray(value)
2021-02-27 20:05:51 -08:00
if len(list) == 0 {
// IncludeFolders is an empty array, everything is included
return true
}
return environment.DirMatchesOneOf(segment.env, segment.env.Pwd(), list)
2021-02-27 20:05:51 -08:00
}
func (segment *Segment) cwdExcluded() bool {
value, ok := segment.Properties[properties.ExcludeFolders]
2021-02-27 20:05:51 -08:00
if !ok {
value = segment.Properties[properties.IgnoreFolders]
2021-02-27 20:05:51 -08:00
}
list := properties.ParseStringArray(value)
return environment.DirMatchesOneOf(segment.env, segment.env.Pwd(), list)
2020-10-02 07:58:25 -07:00
}
func (segment *Segment) getColor(templates []string, defaultColor string) string {
if len(templates) == 0 {
return defaultColor
}
txtTemplate := &textTemplate{
Context: segment.writer,
Env: segment.env,
}
for _, template := range templates {
txtTemplate.Template = template
2021-04-11 06:24:03 -07:00
value, err := txtTemplate.render()
if err != nil || value == "" {
continue
}
return value
}
return defaultColor
}
2021-06-05 07:14:44 -07:00
func (segment *Segment) shouldInvokeWithTip(tip string) bool {
for _, t := range segment.Tips {
if t == tip {
return true
}
}
return false
}
func (segment *Segment) foreground() string {
return segment.getColor(segment.ForegroundTemplates, segment.Foreground)
}
func (segment *Segment) background() string {
return segment.getColor(segment.BackgroundTemplates, segment.Background)
}
func (segment *Segment) mapSegmentWithWriter(env environment.Environment) error {
segment.env = env
2019-03-13 04:14:30 -07:00
functions := map[SegmentType]SegmentWriter{
2022-01-26 05:10:18 -08:00
OWM: &Owm{},
SESSION: &Session{},
PATH: &Path{},
GIT: &Git{},
PLASTIC: &Plastic{},
EXIT: &Exit{},
PYTHON: &Python{},
ROOT: &Root{},
TEXT: &Text{},
TIME: &Time{},
CMD: &Cmd{},
BATTERY: &Battery{},
SPOTIFY: &Spotify{},
SHELL: &Shell{},
NODE: &Node{},
OS: &Os{},
AZ: &Az{},
KUBECTL: &Kubectl{},
DOTNET: &Dotnet{},
TERRAFORM: &Terraform{},
GOLANG: &Golang{},
JULIA: &Julia{},
YTM: &Ytm{},
EXECUTIONTIME: &Executiontime{},
RUBY: &Ruby{},
AWS: &Aws{},
JAVA: &Java{},
POSHGIT: &PoshGit{},
AZFUNC: &AzFunc{},
CRYSTAL: &Crystal{},
DART: &Dart{},
NBGV: &Nbgv{},
RUST: &Rust{},
SYSTEMINFO: &SystemInfo{},
ANGULAR: &Angular{},
PHP: &Php{},
NIGHTSCOUT: &Nightscout{},
STRAVA: &Strava{},
WAKATIME: &Wakatime{},
WIFI: &Wifi{},
WINREG: &WindowsRegistry{},
BREWFATHER: &Brewfather{},
IPIFY: &IPify{},
2019-03-13 04:14:30 -07:00
}
if segment.Properties == nil {
segment.Properties = make(properties.Map)
}
2019-03-13 04:14:30 -07:00
if writer, ok := functions[segment.Type]; ok {
writer.Init(segment.Properties, env)
2019-03-13 04:14:30 -07:00
segment.writer = writer
return nil
2019-03-13 04:14:30 -07:00
}
return errors.New("unable to map writer")
2019-03-13 04:14:30 -07:00
}
func (segment *Segment) setStringValue(env environment.Environment) {
defer func() {
err := recover()
if err == nil {
return
}
// display a message explaining omp failed(with the err)
message := fmt.Sprintf("\noh-my-posh fatal error rendering %s segment:%s\n\n%s\n", segment.Type, err, debug.Stack())
fmt.Println(message)
segment.stringValue = "error"
segment.active = true
}()
err := segment.mapSegmentWithWriter(env)
if err != nil || !segment.shouldIncludeFolder() {
return
}
if segment.enabled() {
segment.stringValue = segment.string()
}
}