oh-my-posh/src/segment.go

297 lines
8.8 KiB
Go
Raw Normal View History

2019-03-13 04:14:30 -07:00
package main
import (
"errors"
"fmt"
"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 {
2021-11-26 01:37:33 -08:00
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 `config:"properties"`
writer SegmentWriter
stringValue string
active bool
env environmentInfo
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
string() string
2021-11-26 01:37:33 -08:00
init(props properties, env environmentInfo)
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 (
// Session represents the user info segment
2019-03-13 04:14:30 -07:00
Session SegmentType = "session"
// Path represents the current path segment
2019-03-13 04:14:30 -07:00
Path SegmentType = "path"
// Git represents the git status and information
2019-03-13 04:14:30 -07:00
Git SegmentType = "git"
// Exit writes the last exit code
2019-03-13 04:14:30 -07:00
Exit SegmentType = "exit"
// Python writes the virtual env name
Python SegmentType = "python"
// Root writes root symbol
2019-03-13 04:14:30 -07:00
Root SegmentType = "root"
// Time writes the current timestamp
2019-03-13 04:14:30 -07:00
Time SegmentType = "time"
// Text writes a text
2019-03-13 04:14:30 -07:00
Text SegmentType = "text"
// Cmd writes the output of a shell command
2019-03-13 04:14:30 -07:00
Cmd SegmentType = "command"
// Battery writes the battery percentage
2019-03-13 04:14:30 -07:00
Battery SegmentType = "battery"
// Spotify writes the Spotify status for Mac
2019-03-13 04:14:30 -07:00
Spotify SegmentType = "spotify"
// ShellInfo writes which shell we're currently in
2020-09-15 04:44:53 -07:00
ShellInfo SegmentType = "shell"
// Node writes which node version is currently active
2020-10-01 11:57:02 -07:00
Node SegmentType = "node"
// Os write os specific icon
2020-10-07 12:01:03 -07:00
Os SegmentType = "os"
// EnvVar writes the content of an environment variable
2020-10-09 10:22:32 -07:00
EnvVar SegmentType = "envvar"
// 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
2020-10-16 07:25:38 -07:00
Terraform SegmentType = "terraform"
// Golang writes which go version is currently active
2020-10-22 04:47:42 -07:00
Golang SegmentType = "go"
2020-11-14 11:04:04 -08:00
// 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"
2020-12-06 13:03:40 -08:00
// ExecutionTime writes the execution time of the last run command
ExecutionTime SegmentType = "executiontime"
2020-10-25 08:32:14 -07:00
// Ruby writes which ruby version is currently active
Ruby SegmentType = "ruby"
2021-02-07 01:55:09 -08:00
// Aws writes the active aws context
Aws SegmentType = "aws"
2021-03-17 00:16:19 -07:00
// Java writes the active java version
Java SegmentType = "java"
2021-03-27 09:04:09 -07:00
// PoshGit writes the posh git prompt
PoshGit SegmentType = "poshgit"
2021-04-02 10:36:50 -07:00
// AZFunc writes current AZ func version
AZFunc SegmentType = "azfunc"
2021-05-14 04:39:49 -07:00
// Crystal writes the active crystal version
Crystal SegmentType = "crystal"
2021-05-14 12:26:26 -07:00
// Dart writes the active dart version
Dart SegmentType = "dart"
2021-06-04 10:27:39 -07:00
// Nbgv writes the nbgv version information
Nbgv SegmentType = "nbgv"
2021-07-04 13:53:10 -07:00
// Rust writes the cargo version information if cargo.toml is present
Rust SegmentType = "rust"
// OWM writes the weather coming from openweatherdata
OWM SegmentType = "owm"
// SysInfo writes system information (memory, cpu, load)
SysInfo SegmentType = "sysinfo"
2021-10-13 00:05:29 -07:00
// 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"
2021-11-23 01:34:35 -08:00
// Nightscout is an open source diabetes system
Nightscout SegmentType = "nightscout"
// WiFi writes details about the current WiFi connection
WiFi SegmentType = "wifi"
2021-11-24 04:47:30 -08:00
// WinReg queries the Windows registry.
WinReg SegmentType = "winreg"
2019-03-13 04:14:30 -07:00
)
func (segment *Segment) string() string {
return segment.writer.string()
}
func (segment *Segment) enabled() bool {
segment.active = segment.writer.enabled()
return segment.active
2019-03-13 04:14:30 -07:00
}
2020-10-02 07:58:25 -07:00
func (segment *Segment) getValue(property Property, defaultValue string) string {
if value, ok := segment.Properties[property]; ok {
return parseString(value, defaultValue)
}
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 {
2021-02-27 20:05:51 -08:00
value, ok := segment.Properties[IncludeFolders]
if !ok {
// IncludeFolders isn't specified, everything is included
return true
}
list := parseStringArray(value)
if len(list) == 0 {
// IncludeFolders is an empty array, everything is included
return true
}
return dirMatchesOneOf(segment.env, segment.env.getcwd(), list)
2021-02-27 20:05:51 -08:00
}
func (segment *Segment) cwdExcluded() bool {
2021-02-27 20:05:51 -08:00
value, ok := segment.Properties[ExcludeFolders]
if !ok {
value = segment.Properties[IgnoreFolders]
}
list := parseStringArray(value)
return dirMatchesOneOf(segment.env, segment.env.getcwd(), 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 {
2021-11-26 01:37:33 -08:00
color := segment.Properties.getColor(ForegroundOverride, segment.Foreground)
return segment.getColor(segment.ForegroundTemplates, color)
}
func (segment *Segment) background() string {
2021-11-26 01:37:33 -08:00
color := segment.Properties.getColor(BackgroundOverride, segment.Background)
return segment.getColor(segment.BackgroundTemplates, color)
}
func (segment *Segment) mapSegmentWithWriter(env environmentInfo) error {
segment.env = env
2019-03-13 04:14:30 -07:00
functions := map[SegmentType]SegmentWriter{
2021-08-15 12:11:02 -07:00
OWM: &owm{},
2020-12-06 13:03:40 -08:00
Session: &session{},
Path: &path{},
Git: &git{},
Exit: &exit{},
Python: &python{},
Root: &root{},
Text: &text{},
Time: &tempus{},
Cmd: &command{},
Battery: &batt{},
Spotify: &spotify{},
ShellInfo: &shell{},
Node: &node{},
Os: &osInfo{},
EnvVar: &envvar{},
Az: &az{},
Kubectl: &kubectl{},
Dotnet: &dotnet{},
Terraform: &terraform{},
Golang: &golang{},
Julia: &julia{},
YTM: &ytm{},
ExecutionTime: &executiontime{},
2020-10-25 08:32:14 -07:00
Ruby: &ruby{},
2021-02-07 01:55:09 -08:00
Aws: &aws{},
2021-03-17 00:16:19 -07:00
Java: &java{},
2021-03-27 09:04:09 -07:00
PoshGit: &poshgit{},
2021-04-02 10:36:50 -07:00
AZFunc: &azfunc{},
2021-05-14 04:39:49 -07:00
Crystal: &crystal{},
2021-05-14 12:26:26 -07:00
Dart: &dart{},
2021-06-04 10:27:39 -07:00
Nbgv: &nbgv{},
2021-07-04 13:53:10 -07:00
Rust: &rust{},
SysInfo: &sysinfo{},
2021-10-13 00:05:29 -07:00
Angular: &angular{},
2021-10-27 01:52:56 -07:00
PHP: &php{},
2021-11-23 01:34:35 -08:00
Nightscout: &nightscout{},
WiFi: &wifi{},
2021-11-24 04:47:30 -08:00
WinReg: &winreg{},
2019-03-13 04:14:30 -07:00
}
if writer, ok := functions[segment.Type]; ok {
2021-11-26 01:37:33 -08:00
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 environmentInfo) {
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()
}
}