mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2025-01-13 20:27:28 -08:00
feat(connection): new segment
BREAKING CHANGE: this will need a manual migration from the wifi segment to the new connection segment.
This commit is contained in:
parent
f60b1715bd
commit
4b6b128d74
|
@ -5,7 +5,6 @@ linters:
|
|||
disable-all: true
|
||||
enable:
|
||||
- bodyclose
|
||||
- deadcode
|
||||
- depguard
|
||||
- dupl
|
||||
- errcheck
|
||||
|
@ -28,12 +27,10 @@ linters:
|
|||
- rowserrcheck
|
||||
- exportloopref
|
||||
- staticcheck
|
||||
- structcheck
|
||||
- typecheck
|
||||
- unconvert
|
||||
- unparam
|
||||
- unused
|
||||
- varcheck
|
||||
- whitespace
|
||||
- lll
|
||||
linters-settings:
|
||||
|
|
|
@ -3,12 +3,11 @@
|
|||
package color
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"oh-my-posh/environment"
|
||||
)
|
||||
|
||||
func GetAccentColor(env environment.Environment) (*RGB, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
return nil, &environment.NotImplemented{}
|
||||
}
|
||||
|
||||
func (d *DefaultColors) SetAccentColor(env environment.Environment, defaultColor string) {
|
||||
|
|
|
@ -96,6 +96,8 @@ const (
|
|||
CMAKE SegmentType = "cmake"
|
||||
// CMD writes the output of a shell command
|
||||
CMD SegmentType = "command"
|
||||
// CONNECTION writes a connection's information
|
||||
CONNECTION SegmentType = "connection"
|
||||
// CRYSTAL writes the active crystal version
|
||||
CRYSTAL SegmentType = "crystal"
|
||||
// DART writes the active dart version
|
||||
|
@ -192,8 +194,6 @@ const (
|
|||
UI5TOOLING SegmentType = "ui5tooling"
|
||||
// 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"
|
||||
// WITHINGS queries the Withings API.
|
||||
|
@ -277,6 +277,7 @@ func (segment *Segment) mapSegmentWithWriter(env environment.Environment) error
|
|||
CF: &segments.Cf{},
|
||||
CFTARGET: &segments.CfTarget{},
|
||||
CMD: &segments.Cmd{},
|
||||
CONNECTION: &segments.Connection{},
|
||||
CRYSTAL: &segments.Crystal{},
|
||||
CMAKE: &segments.Cmake{},
|
||||
DART: &segments.Dart{},
|
||||
|
@ -326,7 +327,6 @@ func (segment *Segment) mapSegmentWithWriter(env environment.Environment) error
|
|||
TIME: &segments.Time{},
|
||||
UI5TOOLING: &segments.UI5Tooling{},
|
||||
WAKATIME: &segments.Wakatime{},
|
||||
WIFI: &segments.Wifi{},
|
||||
WINREG: &segments.WindowsRegistry{},
|
||||
WITHINGS: &segments.Withings{},
|
||||
YTM: &segments.Ytm{},
|
||||
|
|
|
@ -98,20 +98,27 @@ type WindowsRegistryValue struct {
|
|||
String string
|
||||
}
|
||||
|
||||
type WifiType string
|
||||
type NotImplemented struct{}
|
||||
|
||||
type WifiInfo struct {
|
||||
SSID string
|
||||
Interface string
|
||||
RadioType WifiType
|
||||
PhysType WifiType
|
||||
Authentication WifiType
|
||||
Cipher WifiType
|
||||
Channel int
|
||||
ReceiveRate int
|
||||
TransmitRate int
|
||||
Signal int
|
||||
Error string
|
||||
func (n *NotImplemented) Error() string {
|
||||
return "not implemented"
|
||||
}
|
||||
|
||||
type ConnectionType string
|
||||
|
||||
const (
|
||||
ETHERNET ConnectionType = "ethernet"
|
||||
WIFI ConnectionType = "wifi"
|
||||
CELLULAR ConnectionType = "cellular"
|
||||
BLUETOOTH ConnectionType = "bluetooth"
|
||||
)
|
||||
|
||||
type Connection struct {
|
||||
Name string
|
||||
Type ConnectionType
|
||||
TransmitRate uint64
|
||||
ReceiveRate uint64
|
||||
SSID string // Wi-Fi only
|
||||
}
|
||||
|
||||
type TemplateCache struct {
|
||||
|
@ -182,7 +189,7 @@ type Environment interface {
|
|||
InWSLSharedDrive() bool
|
||||
ConvertToLinuxPath(path string) string
|
||||
ConvertToWindowsPath(path string) string
|
||||
WifiNetwork() (*WifiInfo, error)
|
||||
Connection(connectionType ConnectionType) (*Connection, error)
|
||||
TemplateCache() *TemplateCache
|
||||
LoadTemplateCache()
|
||||
Log(logType LogType, funcName, message string)
|
||||
|
@ -222,6 +229,7 @@ type ShellEnvironment struct {
|
|||
fileCache *fileCache
|
||||
tmplCache *TemplateCache
|
||||
logBuilder strings.Builder
|
||||
networks []*Connection
|
||||
}
|
||||
|
||||
func (env *ShellEnvironment) Init() {
|
||||
|
|
|
@ -23,7 +23,7 @@ func (env *ShellEnvironment) Home() string {
|
|||
}
|
||||
|
||||
func (env *ShellEnvironment) QueryWindowTitles(processName, windowTitleRegex string) (string, error) {
|
||||
return "", errors.New("not implemented")
|
||||
return "", &NotImplemented{}
|
||||
}
|
||||
|
||||
func (env *ShellEnvironment) IsWsl() bool {
|
||||
|
@ -94,7 +94,7 @@ func (env *ShellEnvironment) CachePath() string {
|
|||
}
|
||||
|
||||
func (env *ShellEnvironment) WindowsRegistryKeyValue(path string) (*WindowsRegistryValue, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
return nil, &NotImplemented{}
|
||||
}
|
||||
|
||||
func (env *ShellEnvironment) InWSLSharedDrive() bool {
|
||||
|
@ -120,10 +120,6 @@ func (env *ShellEnvironment) ConvertToLinuxPath(path string) string {
|
|||
return path
|
||||
}
|
||||
|
||||
func (env *ShellEnvironment) WifiNetwork() (*WifiInfo, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (env *ShellEnvironment) LookWinAppPath(file string) (string, error) {
|
||||
return "", errors.New("not relevant")
|
||||
}
|
||||
|
@ -160,3 +156,11 @@ func (env *ShellEnvironment) DirIsWritable(path string) bool {
|
|||
|
||||
return true
|
||||
}
|
||||
|
||||
func (env *ShellEnvironment) Connection(connectionType ConnectionType) (*Connection, error) {
|
||||
// added to disable the linting error, we can implement this later
|
||||
if len(env.networks) == 0 {
|
||||
return nil, &NotImplemented{}
|
||||
}
|
||||
return nil, &NotImplemented{}
|
||||
}
|
||||
|
|
|
@ -8,8 +8,6 @@ import (
|
|||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
|
||||
"github.com/Azure/go-ansiterm/winterm"
|
||||
"golang.org/x/sys/windows"
|
||||
|
@ -235,248 +233,6 @@ func (env *ShellEnvironment) ConvertToLinuxPath(path string) string {
|
|||
return path
|
||||
}
|
||||
|
||||
var (
|
||||
hapi = syscall.NewLazyDLL("wlanapi.dll")
|
||||
hWlanOpenHandle = hapi.NewProc("WlanOpenHandle")
|
||||
hWlanCloseHandle = hapi.NewProc("WlanCloseHandle")
|
||||
hWlanEnumInterfaces = hapi.NewProc("WlanEnumInterfaces")
|
||||
hWlanQueryInterface = hapi.NewProc("WlanQueryInterface")
|
||||
)
|
||||
|
||||
const (
|
||||
FHSS WifiType = "FHSS"
|
||||
DSSS WifiType = "DSSS"
|
||||
IR WifiType = "IR"
|
||||
A WifiType = "802.11a"
|
||||
HRDSSS WifiType = "HRDSSS"
|
||||
G WifiType = "802.11g"
|
||||
N WifiType = "802.11n"
|
||||
AC WifiType = "802.11ac"
|
||||
|
||||
Infrastructure WifiType = "Infrastructure"
|
||||
Independent WifiType = "Independent"
|
||||
Any WifiType = "Any"
|
||||
|
||||
OpenSystem WifiType = "802.11 Open System"
|
||||
SharedKey WifiType = "802.11 Shared Key"
|
||||
WPA WifiType = "WPA"
|
||||
WPAPSK WifiType = "WPA PSK"
|
||||
WPANone WifiType = "WPA NONE"
|
||||
WPA2 WifiType = "WPA2"
|
||||
WPA2PSK WifiType = "WPA2 PSK"
|
||||
Disabled WifiType = "disabled"
|
||||
|
||||
None WifiType = "None"
|
||||
WEP40 WifiType = "WEP40"
|
||||
TKIP WifiType = "TKIP"
|
||||
CCMP WifiType = "CCMP"
|
||||
WEP104 WifiType = "WEP104"
|
||||
WEP WifiType = "WEP"
|
||||
)
|
||||
|
||||
func (env *ShellEnvironment) WifiNetwork() (*WifiInfo, error) {
|
||||
env.Trace(time.Now(), "WifiNetwork")
|
||||
// Open handle
|
||||
var pdwNegotiatedVersion uint32
|
||||
var phClientHandle uint32
|
||||
e, _, err := hWlanOpenHandle.Call(uintptr(uint32(2)), uintptr(unsafe.Pointer(nil)), uintptr(unsafe.Pointer(&pdwNegotiatedVersion)), uintptr(unsafe.Pointer(&phClientHandle)))
|
||||
if e != 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// defer closing handle
|
||||
defer func() {
|
||||
_, _, _ = hWlanCloseHandle.Call(uintptr(phClientHandle), uintptr(unsafe.Pointer(nil)))
|
||||
}()
|
||||
|
||||
// list interfaces
|
||||
var interfaceList *WLAN_INTERFACE_INFO_LIST
|
||||
e, _, err = hWlanEnumInterfaces.Call(uintptr(phClientHandle), uintptr(unsafe.Pointer(nil)), uintptr(unsafe.Pointer(&interfaceList)))
|
||||
if e != 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// use first interface that is connected
|
||||
numberOfInterfaces := int(interfaceList.dwNumberOfItems)
|
||||
infoSize := unsafe.Sizeof(interfaceList.InterfaceInfo[0])
|
||||
for i := 0; i < numberOfInterfaces; i++ {
|
||||
network := (*WLAN_INTERFACE_INFO)(unsafe.Pointer(uintptr(unsafe.Pointer(&interfaceList.InterfaceInfo[0])) + uintptr(i)*infoSize))
|
||||
if network.isState != 1 {
|
||||
continue
|
||||
}
|
||||
return env.parseNetworkInterface(network, phClientHandle)
|
||||
}
|
||||
return nil, errors.New("Not connected")
|
||||
}
|
||||
|
||||
func (env *ShellEnvironment) parseNetworkInterface(network *WLAN_INTERFACE_INFO, clientHandle uint32) (*WifiInfo, error) {
|
||||
info := WifiInfo{}
|
||||
info.Interface = strings.TrimRight(string(utf16.Decode(network.strInterfaceDescription[:])), "\x00")
|
||||
|
||||
// Query wifi connection state
|
||||
var dataSize uint16
|
||||
var wlanAttr *WLAN_CONNECTION_ATTRIBUTES
|
||||
e, _, err := hWlanQueryInterface.Call(uintptr(clientHandle),
|
||||
uintptr(unsafe.Pointer(&network.InterfaceGuid)),
|
||||
uintptr(7), // wlan_intf_opcode_current_connection
|
||||
uintptr(unsafe.Pointer(nil)),
|
||||
uintptr(unsafe.Pointer(&dataSize)),
|
||||
uintptr(unsafe.Pointer(&wlanAttr)),
|
||||
uintptr(unsafe.Pointer(nil)))
|
||||
if e != 0 {
|
||||
env.Log(Error, "parseNetworkInterface", "wlan_intf_opcode_current_connection error")
|
||||
return &info, err
|
||||
}
|
||||
|
||||
// SSID
|
||||
ssid := wlanAttr.wlanAssociationAttributes.dot11Ssid
|
||||
if ssid.uSSIDLength > 0 {
|
||||
info.SSID = string(ssid.ucSSID[0:ssid.uSSIDLength])
|
||||
}
|
||||
|
||||
// see https://docs.microsoft.com/en-us/windows/win32/nativewifi/dot11-phy-type
|
||||
switch wlanAttr.wlanAssociationAttributes.dot11PhyType {
|
||||
case 1:
|
||||
info.PhysType = FHSS
|
||||
case 2:
|
||||
info.PhysType = DSSS
|
||||
case 3:
|
||||
info.PhysType = IR
|
||||
case 4:
|
||||
info.PhysType = A
|
||||
case 5:
|
||||
info.PhysType = HRDSSS
|
||||
case 6:
|
||||
info.PhysType = G
|
||||
case 7:
|
||||
info.PhysType = N
|
||||
case 8:
|
||||
info.PhysType = AC
|
||||
default:
|
||||
info.PhysType = UNKNOWN
|
||||
}
|
||||
|
||||
// see https://docs.microsoft.com/en-us/windows/win32/nativewifi/dot11-bss-type
|
||||
switch wlanAttr.wlanAssociationAttributes.dot11BssType {
|
||||
case 1:
|
||||
info.RadioType = Infrastructure
|
||||
case 2:
|
||||
info.RadioType = Independent
|
||||
default:
|
||||
info.RadioType = Any
|
||||
}
|
||||
|
||||
info.Signal = int(wlanAttr.wlanAssociationAttributes.wlanSignalQuality)
|
||||
info.TransmitRate = int(wlanAttr.wlanAssociationAttributes.ulTxRate) / 1024
|
||||
info.ReceiveRate = int(wlanAttr.wlanAssociationAttributes.ulRxRate) / 1024
|
||||
|
||||
// Query wifi channel
|
||||
dataSize = 0
|
||||
var channel *uint32
|
||||
e, _, err = hWlanQueryInterface.Call(uintptr(clientHandle),
|
||||
uintptr(unsafe.Pointer(&network.InterfaceGuid)),
|
||||
uintptr(8), // wlan_intf_opcode_channel_number
|
||||
uintptr(unsafe.Pointer(nil)),
|
||||
uintptr(unsafe.Pointer(&dataSize)),
|
||||
uintptr(unsafe.Pointer(&channel)),
|
||||
uintptr(unsafe.Pointer(nil)))
|
||||
if e != 0 {
|
||||
env.Log(Error, "parseNetworkInterface", "wlan_intf_opcode_channel_number error")
|
||||
return &info, err
|
||||
}
|
||||
info.Channel = int(*channel)
|
||||
|
||||
if wlanAttr.wlanSecurityAttributes.bSecurityEnabled <= 0 {
|
||||
info.Authentication = Disabled
|
||||
return &info, nil
|
||||
}
|
||||
|
||||
// see https://docs.microsoft.com/en-us/windows/win32/nativewifi/dot11-auth-algorithm
|
||||
switch wlanAttr.wlanSecurityAttributes.dot11AuthAlgorithm {
|
||||
case 1:
|
||||
info.Authentication = OpenSystem
|
||||
case 2:
|
||||
info.Authentication = SharedKey
|
||||
case 3:
|
||||
info.Authentication = WPA
|
||||
case 4:
|
||||
info.Authentication = WPAPSK
|
||||
case 5:
|
||||
info.Authentication = WPANone
|
||||
case 6:
|
||||
info.Authentication = WPA2
|
||||
case 7:
|
||||
info.Authentication = WPA2PSK
|
||||
default:
|
||||
info.Authentication = UNKNOWN
|
||||
}
|
||||
|
||||
// see https://docs.microsoft.com/en-us/windows/win32/nativewifi/dot11-cipher-algorithm
|
||||
switch wlanAttr.wlanSecurityAttributes.dot11CipherAlgorithm {
|
||||
case 0:
|
||||
info.Cipher = None
|
||||
case 0x1:
|
||||
info.Cipher = WEP40
|
||||
case 0x2:
|
||||
info.Cipher = TKIP
|
||||
case 0x4:
|
||||
info.Cipher = CCMP
|
||||
case 0x5:
|
||||
info.Cipher = WEP104
|
||||
case 0x100:
|
||||
info.Cipher = WPA
|
||||
case 0x101:
|
||||
info.Cipher = WEP
|
||||
default:
|
||||
info.Cipher = UNKNOWN
|
||||
}
|
||||
|
||||
return &info, nil
|
||||
}
|
||||
|
||||
type WLAN_INTERFACE_INFO_LIST struct { //nolint: revive
|
||||
dwNumberOfItems uint32
|
||||
dwIndex uint32 //nolint: unused
|
||||
InterfaceInfo [1]WLAN_INTERFACE_INFO
|
||||
}
|
||||
|
||||
type WLAN_INTERFACE_INFO struct { //nolint: revive
|
||||
InterfaceGuid syscall.GUID //nolint: revive
|
||||
strInterfaceDescription [256]uint16
|
||||
isState uint32
|
||||
}
|
||||
|
||||
type WLAN_CONNECTION_ATTRIBUTES struct { //nolint: revive
|
||||
isState uint32 //nolint: unused
|
||||
wlanConnectionMode uint32 //nolint: unused
|
||||
strProfileName [256]uint16 //nolint: unused
|
||||
wlanAssociationAttributes WLAN_ASSOCIATION_ATTRIBUTES
|
||||
wlanSecurityAttributes WLAN_SECURITY_ATTRIBUTES
|
||||
}
|
||||
|
||||
type WLAN_ASSOCIATION_ATTRIBUTES struct { //nolint: revive
|
||||
dot11Ssid DOT11_SSID
|
||||
dot11BssType uint32
|
||||
dot11Bssid [6]uint8 //nolint: unused
|
||||
dot11PhyType uint32
|
||||
uDot11PhyIndex uint32 //nolint: unused
|
||||
wlanSignalQuality uint32
|
||||
ulRxRate uint32
|
||||
ulTxRate uint32
|
||||
}
|
||||
|
||||
type WLAN_SECURITY_ATTRIBUTES struct { //nolint: revive
|
||||
bSecurityEnabled uint32
|
||||
bOneXEnabled uint32 //nolint: unused
|
||||
dot11AuthAlgorithm uint32
|
||||
dot11CipherAlgorithm uint32
|
||||
}
|
||||
|
||||
type DOT11_SSID struct { //nolint: revive
|
||||
uSSIDLength uint32
|
||||
ucSSID [32]uint8
|
||||
}
|
||||
|
||||
func (env *ShellEnvironment) DirIsWritable(path string) bool {
|
||||
defer env.Trace(time.Now(), "DirIsWritable")
|
||||
info, err := os.Stat(path)
|
||||
|
@ -498,3 +254,20 @@ func (env *ShellEnvironment) DirIsWritable(path string) bool {
|
|||
|
||||
return true
|
||||
}
|
||||
|
||||
func (env *ShellEnvironment) Connection(connectionType ConnectionType) (*Connection, error) {
|
||||
if env.networks == nil {
|
||||
networks := env.getConnections()
|
||||
if len(networks) == 0 {
|
||||
return nil, errors.New("No connections found")
|
||||
}
|
||||
env.networks = networks
|
||||
}
|
||||
for _, network := range env.networks {
|
||||
if network.Type == connectionType {
|
||||
return network, nil
|
||||
}
|
||||
}
|
||||
env.Log(Error, "network", fmt.Sprintf("Network type '%s' not found", connectionType))
|
||||
return nil, &NotImplemented{}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,9 @@ var (
|
|||
|
||||
psapi = syscall.NewLazyDLL("psapi.dll")
|
||||
getModuleBaseNameA = psapi.NewProc("GetModuleBaseNameA")
|
||||
|
||||
iphlpapi = syscall.NewLazyDLL("iphlpapi.dll")
|
||||
hGetIfTable2 = iphlpapi.NewProc("GetIfTable2")
|
||||
)
|
||||
|
||||
// enumWindows call enumWindows from user32 and returns all active windows
|
||||
|
@ -189,7 +192,242 @@ func readWinAppLink(path string) (string, error) {
|
|||
rb := (*GenericDataBuffer)(unsafe.Pointer(&rdb.DUMMYUNIONNAME))
|
||||
appExecLink := (*AppExecLinkReparseBuffer)(unsafe.Pointer(&rb.DataBuffer))
|
||||
if appExecLink.Version != 3 {
|
||||
return " ", errors.New("unknown AppExecLink version")
|
||||
return "", errors.New("unknown AppExecLink version")
|
||||
}
|
||||
return appExecLink.Path()
|
||||
}
|
||||
|
||||
// networks
|
||||
|
||||
func (env *ShellEnvironment) getConnections() []*Connection {
|
||||
var pIFTable2 *MIN_IF_TABLE2
|
||||
_, _, _ = hGetIfTable2.Call(uintptr(unsafe.Pointer(&pIFTable2)))
|
||||
|
||||
SSIDs, _ := env.getAllWifiSSID()
|
||||
networks := make([]*Connection, 0)
|
||||
|
||||
for i := 0; i < int(pIFTable2.NumEntries); i++ {
|
||||
networkInterface := pIFTable2.Table[i]
|
||||
alias := strings.TrimRight(syscall.UTF16ToString(networkInterface.Alias[:]), "\x00")
|
||||
description := strings.TrimRight(syscall.UTF16ToString(networkInterface.Description[:]), "\x00")
|
||||
|
||||
if networkInterface.OperStatus != 1 || // not connected or functional
|
||||
!networkInterface.InterfaceAndOperStatusFlags.HardwareInterface || // rule out software interfaces
|
||||
strings.HasPrefix(alias, "Local Area Connection") || // not relevant
|
||||
strings.Index(alias, "-") >= 3 { // rule out parts of Ethernet filter interfaces
|
||||
// e.g. : "Ethernet-WFP Native MAC Layer LightWeight Filter-0000"
|
||||
continue
|
||||
}
|
||||
|
||||
var connectionType ConnectionType
|
||||
switch networkInterface.Type {
|
||||
case 6:
|
||||
connectionType = ETHERNET
|
||||
case 71:
|
||||
connectionType = WIFI
|
||||
case 237, 234, 244:
|
||||
connectionType = CELLULAR
|
||||
}
|
||||
|
||||
if networkInterface.PhysicalMediumType == 10 {
|
||||
connectionType = BLUETOOTH
|
||||
}
|
||||
|
||||
// skip connections which aren't relevant
|
||||
if len(connectionType) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
network := &Connection{
|
||||
Type: connectionType,
|
||||
Name: description, // we want a relatable name, alias isn't that
|
||||
TransmitRate: networkInterface.TransmitLinkSpeed,
|
||||
ReceiveRate: networkInterface.ReceiveLinkSpeed,
|
||||
}
|
||||
|
||||
if SSID, OK := SSIDs[network.Name]; OK {
|
||||
network.SSID = SSID
|
||||
}
|
||||
|
||||
networks = append(networks, network)
|
||||
}
|
||||
return networks
|
||||
}
|
||||
|
||||
type MIN_IF_TABLE2 struct { //nolint: revive
|
||||
NumEntries uint64
|
||||
Table [256]MIB_IF_ROW2
|
||||
}
|
||||
|
||||
const (
|
||||
IF_MAX_STRING_SIZE uint64 = 256 //nolint: revive
|
||||
IF_MAX_PHYS_ADDRESS_LENGTH uint64 = 32 //nolint: revive
|
||||
)
|
||||
|
||||
type MIB_IF_ROW2 struct { //nolint: revive
|
||||
InterfaceLuid uint64
|
||||
InterfaceIndex uint32
|
||||
InterfaceGUID windows.GUID
|
||||
Alias [IF_MAX_STRING_SIZE + 1]uint16
|
||||
Description [IF_MAX_STRING_SIZE + 1]uint16
|
||||
PhysicalAddressLength uint32
|
||||
PhysicalAddress [IF_MAX_PHYS_ADDRESS_LENGTH]uint8
|
||||
PermanentPhysicalAddress [IF_MAX_PHYS_ADDRESS_LENGTH]uint8
|
||||
|
||||
Mtu uint32
|
||||
Type uint32
|
||||
TunnelType uint32
|
||||
MediaType uint32
|
||||
PhysicalMediumType uint32
|
||||
AccessType uint32
|
||||
DirectionType uint32
|
||||
|
||||
InterfaceAndOperStatusFlags struct {
|
||||
HardwareInterface bool
|
||||
FilterInterface bool
|
||||
ConnectorPresent bool
|
||||
NotAuthenticated bool
|
||||
NotMediaConnected bool
|
||||
Paused bool
|
||||
LowPower bool
|
||||
EndPointInterface bool
|
||||
}
|
||||
|
||||
OperStatus uint32
|
||||
AdminStatus uint32
|
||||
MediaConnectState uint32
|
||||
NetworkGUID windows.GUID
|
||||
ConnectionType uint32
|
||||
|
||||
TransmitLinkSpeed uint64
|
||||
ReceiveLinkSpeed uint64
|
||||
|
||||
InOctets uint64
|
||||
InUcastPkts uint64
|
||||
InNUcastPkts uint64
|
||||
InDiscards uint64
|
||||
InErrors uint64
|
||||
InUnknownProtos uint64
|
||||
InUcastOctets uint64
|
||||
InMulticastOctets uint64
|
||||
InBroadcastOctets uint64
|
||||
OutOctets uint64
|
||||
OutUcastPkts uint64
|
||||
OutNUcastPkts uint64
|
||||
OutDiscards uint64
|
||||
OutErrors uint64
|
||||
OutUcastOctets uint64
|
||||
OutMulticastOctets uint64
|
||||
OutBroadcastOctets uint64
|
||||
OutQLen uint64
|
||||
}
|
||||
|
||||
func (env *ShellEnvironment) getAllWifiSSID() (map[string]string, error) {
|
||||
var pdwNegotiatedVersion uint32
|
||||
var phClientHandle uint32
|
||||
e, _, err := hWlanOpenHandle.Call(uintptr(uint32(2)), uintptr(unsafe.Pointer(nil)), uintptr(unsafe.Pointer(&pdwNegotiatedVersion)), uintptr(unsafe.Pointer(&phClientHandle)))
|
||||
if e != 0 {
|
||||
env.Log(Error, "getAllWifiSSID", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// defer closing handle
|
||||
defer func() {
|
||||
_, _, _ = hWlanCloseHandle.Call(uintptr(phClientHandle), uintptr(unsafe.Pointer(nil)))
|
||||
}()
|
||||
|
||||
ssid := make(map[string]string)
|
||||
// list interfaces
|
||||
var interfaceList *WLAN_INTERFACE_INFO_LIST
|
||||
e, _, err = hWlanEnumInterfaces.Call(uintptr(phClientHandle), uintptr(unsafe.Pointer(nil)), uintptr(unsafe.Pointer(&interfaceList)))
|
||||
if e != 0 {
|
||||
env.Log(Error, "getAllWifiSSID", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// use first interface that is connected
|
||||
numberOfInterfaces := int(interfaceList.dwNumberOfItems)
|
||||
infoSize := unsafe.Sizeof(interfaceList.InterfaceInfo[0])
|
||||
for i := 0; i < numberOfInterfaces; i++ {
|
||||
network := (*WLAN_INTERFACE_INFO)(unsafe.Pointer(uintptr(unsafe.Pointer(&interfaceList.InterfaceInfo[0])) + uintptr(i)*infoSize))
|
||||
if network.isState == 1 {
|
||||
wifiInterface := strings.TrimRight(string(utf16.Decode(network.strInterfaceDescription[:])), "\x00")
|
||||
ssid[wifiInterface] = env.getWiFiSSID(network, phClientHandle)
|
||||
}
|
||||
}
|
||||
return ssid, nil
|
||||
}
|
||||
|
||||
var (
|
||||
wlanapi = syscall.NewLazyDLL("wlanapi.dll")
|
||||
hWlanOpenHandle = wlanapi.NewProc("WlanOpenHandle")
|
||||
hWlanCloseHandle = wlanapi.NewProc("WlanCloseHandle")
|
||||
hWlanEnumInterfaces = wlanapi.NewProc("WlanEnumInterfaces")
|
||||
hWlanQueryInterface = wlanapi.NewProc("WlanQueryInterface")
|
||||
)
|
||||
|
||||
func (env *ShellEnvironment) getWiFiSSID(network *WLAN_INTERFACE_INFO, clientHandle uint32) string {
|
||||
// Query wifi connection state
|
||||
var dataSize uint16
|
||||
var wlanAttr *WLAN_CONNECTION_ATTRIBUTES
|
||||
e, _, _ := hWlanQueryInterface.Call(uintptr(clientHandle),
|
||||
uintptr(unsafe.Pointer(&network.InterfaceGuid)),
|
||||
uintptr(7), // wlan_intf_opcode_current_connection
|
||||
uintptr(unsafe.Pointer(nil)),
|
||||
uintptr(unsafe.Pointer(&dataSize)),
|
||||
uintptr(unsafe.Pointer(&wlanAttr)),
|
||||
uintptr(unsafe.Pointer(nil)))
|
||||
if e != 0 {
|
||||
env.Log(Error, "parseWlanInterface", "wlan_intf_opcode_current_connection error")
|
||||
return ""
|
||||
}
|
||||
|
||||
ssid := wlanAttr.wlanAssociationAttributes.dot11Ssid
|
||||
if ssid.uSSIDLength <= 0 {
|
||||
return ""
|
||||
}
|
||||
return string(ssid.ucSSID[0:ssid.uSSIDLength])
|
||||
}
|
||||
|
||||
type WLAN_INTERFACE_INFO_LIST struct { //nolint: revive
|
||||
dwNumberOfItems uint32
|
||||
dwIndex uint32 //nolint: unused
|
||||
InterfaceInfo [256]WLAN_INTERFACE_INFO
|
||||
}
|
||||
|
||||
type WLAN_INTERFACE_INFO struct { //nolint: revive
|
||||
InterfaceGuid syscall.GUID //nolint: revive
|
||||
strInterfaceDescription [256]uint16
|
||||
isState uint32
|
||||
}
|
||||
|
||||
type WLAN_CONNECTION_ATTRIBUTES struct { //nolint: revive
|
||||
isState uint32 //nolint: unused
|
||||
wlanConnectionMode uint32 //nolint: unused
|
||||
strProfileName [256]uint16 //nolint: unused
|
||||
wlanAssociationAttributes WLAN_ASSOCIATION_ATTRIBUTES
|
||||
wlanSecurityAttributes WLAN_SECURITY_ATTRIBUTES //nolint: unused
|
||||
}
|
||||
|
||||
type WLAN_ASSOCIATION_ATTRIBUTES struct { //nolint: revive
|
||||
dot11Ssid DOT11_SSID
|
||||
dot11BssType uint32 //nolint: unused
|
||||
dot11Bssid [6]uint8 //nolint: unused
|
||||
dot11PhyType uint32 //nolint: unused
|
||||
uDot11PhyIndex uint32 //nolint: unused
|
||||
wlanSignalQuality uint32 //nolint: unused
|
||||
ulRxRate uint32 //nolint: unused
|
||||
ulTxRate uint32 //nolint: unused
|
||||
}
|
||||
|
||||
type WLAN_SECURITY_ATTRIBUTES struct { //nolint: revive
|
||||
bSecurityEnabled uint32 //nolint: unused
|
||||
bOneXEnabled uint32 //nolint: unused
|
||||
dot11AuthAlgorithm uint32 //nolint: unused
|
||||
dot11CipherAlgorithm uint32 //nolint: unused
|
||||
}
|
||||
|
||||
type DOT11_SSID struct { //nolint: revive
|
||||
uSSIDLength uint32
|
||||
ucSSID [32]uint8
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ require (
|
|||
github.com/hashicorp/hcl/v2 v2.14.0
|
||||
github.com/mattn/go-runewidth v0.0.13
|
||||
github.com/spf13/cobra v1.5.0
|
||||
golang.org/x/mod v0.5.1
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
|
@ -60,7 +60,6 @@ require (
|
|||
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
||||
github.com/tklauser/numcpus v0.5.0 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
|
@ -222,8 +222,8 @@ golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0
|
|||
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E=
|
||||
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69 h1:Lj6HJGCSn5AjxRAH2+r35Mir4icalbqku+CLUtjnvXY=
|
||||
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
|
||||
golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
|
||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
|
@ -265,8 +265,6 @@ golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
|||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
|
|
@ -208,9 +208,9 @@ func (env *MockedEnvironment) ConvertToLinuxPath(path string) string {
|
|||
return args.String(0)
|
||||
}
|
||||
|
||||
func (env *MockedEnvironment) WifiNetwork() (*environment.WifiInfo, error) {
|
||||
args := env.Called()
|
||||
return args.Get(0).(*environment.WifiInfo), args.Error(1)
|
||||
func (env *MockedEnvironment) Connection(connectionType environment.ConnectionType) (*environment.Connection, error) {
|
||||
args := env.Called(connectionType)
|
||||
return args.Get(0).(*environment.Connection), args.Error(1)
|
||||
}
|
||||
|
||||
func (env *MockedEnvironment) TemplateCache() *environment.TemplateCache {
|
||||
|
|
|
@ -60,15 +60,7 @@ func (m Map) GetString(property Property, defaultValue string) string {
|
|||
if !found {
|
||||
return defaultValue
|
||||
}
|
||||
return ParseString(val, defaultValue)
|
||||
}
|
||||
|
||||
func ParseString(value interface{}, defaultValue string) string {
|
||||
stringValue, ok := value.(string)
|
||||
if !ok {
|
||||
return defaultValue
|
||||
}
|
||||
return stringValue
|
||||
return fmt.Sprint(val)
|
||||
}
|
||||
|
||||
func (m Map) GetColor(property Property, defaultValue string) string {
|
||||
|
@ -76,7 +68,7 @@ func (m Map) GetColor(property Property, defaultValue string) string {
|
|||
if !found {
|
||||
return defaultValue
|
||||
}
|
||||
colorString := ParseString(val, defaultValue)
|
||||
colorString := fmt.Sprint(val)
|
||||
if color.IsAnsiColorName(colorString) {
|
||||
return colorString
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ func TestGetStringNoEntry(t *testing.T) {
|
|||
func TestGetStringNoTextEntry(t *testing.T) {
|
||||
var properties = Map{Foo: true}
|
||||
value := properties.GetString(Foo, expected)
|
||||
assert.Equal(t, expected, value)
|
||||
assert.Equal(t, "true", value)
|
||||
}
|
||||
|
||||
func TestGetHexColor(t *testing.T) {
|
||||
|
|
41
src/segments/connection.go
Normal file
41
src/segments/connection.go
Normal file
|
@ -0,0 +1,41 @@
|
|||
package segments
|
||||
|
||||
import (
|
||||
"oh-my-posh/environment"
|
||||
"oh-my-posh/properties"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Connection struct {
|
||||
props properties.Properties
|
||||
env environment.Environment
|
||||
|
||||
environment.Connection
|
||||
}
|
||||
|
||||
const (
|
||||
Type properties.Property = "type"
|
||||
)
|
||||
|
||||
func (c *Connection) Template() string {
|
||||
return " {{ if eq .Type \"wifi\"}}\uf1eb{{ else if eq .Type \"ethernet\"}}\uf6ff{{ end }} "
|
||||
}
|
||||
|
||||
func (c *Connection) Enabled() bool {
|
||||
types := c.props.GetString(Type, "wifi|ethernet")
|
||||
connectionTypes := strings.Split(types, "|")
|
||||
for _, connectionType := range connectionTypes {
|
||||
network, err := c.env.Connection(environment.ConnectionType(connectionType))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
c.Connection = *network
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *Connection) Init(props properties.Properties, env environment.Environment) {
|
||||
c.props = props
|
||||
c.env = env
|
||||
}
|
105
src/segments/connection_test.go
Normal file
105
src/segments/connection_test.go
Normal file
|
@ -0,0 +1,105 @@
|
|||
package segments
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"oh-my-posh/environment"
|
||||
"oh-my-posh/mock"
|
||||
"oh-my-posh/properties"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestConnection(t *testing.T) {
|
||||
type connectionResponse struct {
|
||||
Connection *environment.Connection
|
||||
Error error
|
||||
}
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
ExpectedEnabled bool
|
||||
ConnectionType string
|
||||
Connections []*connectionResponse
|
||||
}{
|
||||
{
|
||||
Case: "WiFi only, enabled",
|
||||
ExpectedString: "\uf1eb",
|
||||
ExpectedEnabled: true,
|
||||
ConnectionType: "wifi",
|
||||
Connections: []*connectionResponse{
|
||||
{
|
||||
Connection: &environment.Connection{
|
||||
Name: "WiFi",
|
||||
Type: "wifi",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Case: "WiFi only, disabled",
|
||||
ConnectionType: "wifi",
|
||||
Connections: []*connectionResponse{
|
||||
{
|
||||
Connection: &environment.Connection{
|
||||
Type: environment.WIFI,
|
||||
},
|
||||
Error: fmt.Errorf("no connection"),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Case: "WiFi and Ethernet, enabled",
|
||||
ConnectionType: "wifi|ethernet",
|
||||
ExpectedString: "\uf6ff",
|
||||
ExpectedEnabled: true,
|
||||
Connections: []*connectionResponse{
|
||||
{
|
||||
Connection: &environment.Connection{
|
||||
Type: environment.WIFI,
|
||||
},
|
||||
Error: fmt.Errorf("no connection"),
|
||||
},
|
||||
{
|
||||
Connection: &environment.Connection{
|
||||
Type: environment.ETHERNET,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Case: "WiFi and Ethernet, disabled",
|
||||
ConnectionType: "wifi|ethernet",
|
||||
Connections: []*connectionResponse{
|
||||
{
|
||||
Connection: &environment.Connection{
|
||||
Type: environment.WIFI,
|
||||
},
|
||||
Error: fmt.Errorf("no connection"),
|
||||
},
|
||||
{
|
||||
Connection: &environment.Connection{
|
||||
Type: environment.ETHERNET,
|
||||
},
|
||||
Error: fmt.Errorf("no connection"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
env := &mock.MockedEnvironment{}
|
||||
for _, con := range tc.Connections {
|
||||
env.On("Connection", con.Connection.Type).Return(con.Connection, con.Error)
|
||||
}
|
||||
c := &Connection{
|
||||
env: env,
|
||||
props: &properties.Map{
|
||||
Type: tc.ConnectionType,
|
||||
},
|
||||
}
|
||||
assert.Equal(t, tc.ExpectedEnabled, c.Enabled(), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
if tc.ExpectedEnabled {
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, c.Template(), c), fmt.Sprintf("Failed in case: %s", tc.Case))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
package segments
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"oh-my-posh/environment"
|
||||
"oh-my-posh/mock"
|
||||
"oh-my-posh/properties"
|
||||
"testing"
|
||||
|
@ -40,7 +40,7 @@ func TestSpotifyWindowsNative(t *testing.T) {
|
|||
for _, tc := range cases {
|
||||
env := new(mock.MockedEnvironment)
|
||||
env.On("QueryWindowTitles", "spotify.exe", `^(Spotify.*)|(.*\s-\s.*)$`).Return(tc.Title, tc.Error)
|
||||
env.On("QueryWindowTitles", "msedge.exe", `^(Spotify.*)`).Return("", errors.New("not implemented"))
|
||||
env.On("QueryWindowTitles", "msedge.exe", `^(Spotify.*)`).Return("", &environment.NotImplemented{})
|
||||
s := &Spotify{
|
||||
env: env,
|
||||
props: properties.Map{},
|
||||
|
@ -74,7 +74,7 @@ func TestSpotifyWindowsPWA(t *testing.T) {
|
|||
}
|
||||
for _, tc := range cases {
|
||||
env := new(mock.MockedEnvironment)
|
||||
env.On("QueryWindowTitles", "spotify.exe", "^(Spotify.*)|(.*\\s-\\s.*)$").Return("", errors.New("not implemented"))
|
||||
env.On("QueryWindowTitles", "spotify.exe", "^(Spotify.*)|(.*\\s-\\s.*)$").Return("", &environment.NotImplemented{})
|
||||
env.On("QueryWindowTitles", "msedge.exe", "^(Spotify.*)").Return(tc.Title, tc.Error)
|
||||
s := &Spotify{
|
||||
env: env,
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
package segments
|
||||
|
||||
import (
|
||||
"oh-my-posh/environment"
|
||||
"oh-my-posh/properties"
|
||||
)
|
||||
|
||||
type Wifi struct {
|
||||
props properties.Properties
|
||||
env environment.Environment
|
||||
|
||||
Error string
|
||||
|
||||
environment.WifiInfo
|
||||
}
|
||||
|
||||
const (
|
||||
defaultTemplate = " {{ if .Error }}{{ .Error }}{{ else }}\uFAA8 {{ .SSID }} {{ .Signal }}% {{ .ReceiveRate }}Mbps{{ end }} "
|
||||
)
|
||||
|
||||
func (w *Wifi) Template() string {
|
||||
return defaultTemplate
|
||||
}
|
||||
|
||||
func (w *Wifi) Enabled() bool {
|
||||
// This segment only supports Windows/WSL for now
|
||||
if w.env.Platform() != environment.WINDOWS && !w.env.IsWsl() {
|
||||
return false
|
||||
}
|
||||
wifiInfo, err := w.env.WifiNetwork()
|
||||
displayError := w.props.GetBool(properties.DisplayError, false)
|
||||
if err != nil && displayError {
|
||||
w.Error = err.Error()
|
||||
return true
|
||||
}
|
||||
if err != nil || wifiInfo == nil {
|
||||
return false
|
||||
}
|
||||
w.WifiInfo = *wifiInfo
|
||||
return true
|
||||
}
|
||||
|
||||
func (w *Wifi) Init(props properties.Properties, env environment.Environment) {
|
||||
w.props = props
|
||||
w.env = env
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
package segments
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"oh-my-posh/environment"
|
||||
"oh-my-posh/mock"
|
||||
"oh-my-posh/properties"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestWiFiSegment(t *testing.T) {
|
||||
cases := []struct {
|
||||
Case string
|
||||
ExpectedString string
|
||||
ExpectedEnabled bool
|
||||
Network *environment.WifiInfo
|
||||
WifiError error
|
||||
DisplayError bool
|
||||
}{
|
||||
{
|
||||
Case: "No error and nil network",
|
||||
},
|
||||
{
|
||||
Case: "Error and nil network",
|
||||
WifiError: errors.New("oh noes"),
|
||||
},
|
||||
{
|
||||
Case: "Display error and nil network",
|
||||
WifiError: errors.New("oh noes"),
|
||||
ExpectedString: "oh noes",
|
||||
DisplayError: true,
|
||||
ExpectedEnabled: true,
|
||||
},
|
||||
{
|
||||
Case: "Display wifi state",
|
||||
ExpectedString: "pretty fly for a wifi",
|
||||
ExpectedEnabled: true,
|
||||
Network: &environment.WifiInfo{
|
||||
SSID: "pretty fly for a wifi",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
env := new(mock.MockedEnvironment)
|
||||
env.On("Platform").Return(environment.WINDOWS)
|
||||
env.On("IsWsl").Return(false)
|
||||
env.On("WifiNetwork").Return(tc.Network, tc.WifiError)
|
||||
|
||||
w := &Wifi{
|
||||
env: env,
|
||||
props: properties.Map{
|
||||
properties.DisplayError: tc.DisplayError,
|
||||
},
|
||||
}
|
||||
|
||||
assert.Equal(t, tc.ExpectedEnabled, w.Enabled(), tc.Case)
|
||||
if tc.Network != nil || tc.DisplayError {
|
||||
assert.Equal(t, tc.ExpectedString, renderTemplate(env, "{{ if .Error }}{{ .Error }}{{ else }}{{ .SSID }}{{ end }}", w), tc.Case)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -225,6 +225,7 @@
|
|||
"angular",
|
||||
"battery",
|
||||
"command",
|
||||
"connection",
|
||||
"crystal",
|
||||
"cds",
|
||||
"cf",
|
||||
|
@ -274,7 +275,6 @@
|
|||
"terraform",
|
||||
"ui5tooling",
|
||||
"wakatime",
|
||||
"wifi",
|
||||
"winreg",
|
||||
"withings",
|
||||
"ytm"
|
||||
|
@ -575,6 +575,55 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "connection"
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"title": "Connection Segment",
|
||||
"description": "https://ohmyposh.dev/docs/segments/connection",
|
||||
"properties": {
|
||||
"properties": {
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"title": "Connection type",
|
||||
"description": "The connection type to display",
|
||||
"enum": [
|
||||
"ethernet",
|
||||
"wifi",
|
||||
"cellular",
|
||||
"bluetooth"
|
||||
],
|
||||
"default": "wifi|ethernet"
|
||||
},
|
||||
"unit": {
|
||||
"type": "string",
|
||||
"title": "Transfer speed unit",
|
||||
"enum": [
|
||||
"none",
|
||||
"b",
|
||||
"bps",
|
||||
"K",
|
||||
"Kbps",
|
||||
"M",
|
||||
"Mbps",
|
||||
"G",
|
||||
"Gbps",
|
||||
"T",
|
||||
"Tbps"
|
||||
],
|
||||
"default": "none"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
|
@ -2164,19 +2213,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"type": {
|
||||
"const": "wifi"
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"title": "WiFi Segment",
|
||||
"description": "https://ohmyposh.dev/docs/segments/wifi"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
|
|
|
@ -85,7 +85,7 @@ go build -o $GOPATH/bin/oh-my-posh
|
|||
|
||||
## Add the documentation
|
||||
|
||||
Create a new `markdown` file underneath the [`docs/docs/segments`][docs] folder called `new.md`.
|
||||
Create a new `markdown` file underneath the [`website/docs/segments`][docs] folder called `new.md`.
|
||||
Use the following template as a guide.
|
||||
|
||||
````markdown
|
||||
|
|
51
website/docs/segments/connection.mdx
Normal file
51
website/docs/segments/connection.mdx
Normal file
|
@ -0,0 +1,51 @@
|
|||
---
|
||||
id: connection
|
||||
title: Connection
|
||||
sidebar_label: Connection
|
||||
---
|
||||
|
||||
## Connection
|
||||
|
||||
Show details about the currently connected network.
|
||||
|
||||
:::info
|
||||
Currently only supports Windows. Pull requests for Darwin and Linux support are welcome :)
|
||||
:::
|
||||
|
||||
## Sample Configuration
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "connection",
|
||||
"style": "powerline",
|
||||
"background": "#8822ee",
|
||||
"foreground": "#222222",
|
||||
"powerline_symbol": "\uE0B0"
|
||||
}
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Name | Type | Description |
|
||||
| ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `type` | `string` | the type of connection to display. Can be a single value or multiple joined by <inlineCode>\|</inlineCode> . The first to resolve is shown (**default value** is <inlineCode>wifi\|ethernet</inlineCode>). Possible values:<ul><li>`wifi`</li><li>`ethernet`</li><li>`bluetooth`</li><li>`cellular`</li></ul> |
|
||||
|
||||
## Template ([info][templates])
|
||||
|
||||
:::note default template
|
||||
|
||||
```template
|
||||
{{ if eq .Type \"wifi\"}}\uf1eb{{ else if eq .Type \"ethernet\"}}\uf6ff{{ end }}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Description |
|
||||
| ------- | -------- | ------------------------------------------------------- |
|
||||
| `.Type` | `string` | the connection type type. Single values of `type` above |
|
||||
| `.Name` | `string` | the name of the connection |
|
||||
| `.SSID` | `string` | the SSID of the current wifi network |
|
||||
|
||||
[templates]: /docs/configuration/templates
|
|
@ -23,14 +23,14 @@ Display the currently active golang version.
|
|||
|
||||
## Properties
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---------------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `home_enabled` | `boolean` | display the segment in the HOME folder or not - defaults to `false` |
|
||||
| `fetch_version` | `boolean` | display the golang version - defaults to `true` |
|
||||
| `missing_command_text` | `string` | text to display when the command is missing - defaults to empty |
|
||||
| `display_mode` | `string` | <ul><li>`always`: the segment is always displayed</li><li>`files`: the segment is only displayed when `*.go` or `go.mod` files are present (**default**)</li></ul> |
|
||||
| `version_url_template` | `string` | a go [text/template][go-text-template] [template][templates] that creates the URL of the version info / release notes |
|
||||
| `parse_mod_file` | `boolean`: parse the go.mod file instead of calling `go version` |
|
||||
| Name | Type | Description |
|
||||
| ---------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `home_enabled` | `boolean` | display the segment in the HOME folder or not - defaults to `false` |
|
||||
| `fetch_version` | `boolean` | display the golang version - defaults to `true` |
|
||||
| `missing_command_text` | `string` | text to display when the command is missing - defaults to empty |
|
||||
| `display_mode` | `string` | <ul><li>`always`: the segment is always displayed</li><li>`files`: the segment is only displayed when `*.go` or `go.mod` files are present (**default**)</li></ul> |
|
||||
| `version_url_template` | `string` | a go [text/template][go-text-template] [template][templates] that creates the URL of the version info / release notes |
|
||||
| `parse_mod_file` | `boolean` | parse the go.mod file instead of calling `go version` |
|
||||
|
||||
## Template ([info][templates])
|
||||
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
---
|
||||
id: wifi
|
||||
title: WiFi
|
||||
sidebar_label: WiFi
|
||||
---
|
||||
|
||||
## What
|
||||
|
||||
Show details about the currently connected WiFi network.
|
||||
|
||||
:::info
|
||||
Currently only supports Windows and WSL. Pull requests for Darwin and Linux support are welcome :)
|
||||
:::
|
||||
|
||||
## Sample Configuration
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "wifi",
|
||||
"style": "powerline",
|
||||
"background": "#8822ee",
|
||||
"foreground": "#222222",
|
||||
"background_templates": [
|
||||
"{{ if (lt .Signal 60) }}#DDDD11{{ else if (lt .Signal 90) }}#DD6611{{ else }}#11CC11{{ end }}"
|
||||
],
|
||||
"powerline_symbol": "\uE0B0",
|
||||
"template": "\uFAA8 {{ .SSID }} {{ .Signal }}% {{ .ReceiveRate }}Mbps"
|
||||
}
|
||||
```
|
||||
|
||||
## Template ([info][templates])
|
||||
|
||||
:::note default template
|
||||
|
||||
```template
|
||||
{{ if .Error }}{{ .Error }}{{ else }}\uFAA8 {{ .SSID }} {{ .Signal }}% {{ .ReceiveRate }}Mbps{{ end }}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Description |
|
||||
| ----------------- | -------- | --------------------------------------------------------------------- |
|
||||
| `.SSID` | `string` | the SSID of the current wifi network |
|
||||
| `.RadioType` | `string` | the radio type - _e.g. 802.11ac, 802.11ax, 802.11n, etc._ |
|
||||
| `.Authentication` | `string` | the authentication type - _e.g. WPA2-Personal, WPA2-Enterprise, etc._ |
|
||||
| `.Channel` | `int` | the current channel number |
|
||||
| `.ReceiveRate` | `int` | the receive rate (Mbps) |
|
||||
| `.TransmitRate` | `int` | the transmit rate (Mbps) |
|
||||
| `.Signal` | `int` | the signal strength (%) |
|
||||
|
||||
[templates]: /docs/configuration/templates
|
|
@ -58,10 +58,11 @@ module.exports = {
|
|||
"segments/battery",
|
||||
"segments/brewfather",
|
||||
"segments/cds",
|
||||
"segments/command",
|
||||
"segments/cf",
|
||||
"segments/cftarget",
|
||||
"segments/cmake",
|
||||
"segments/command",
|
||||
"segments/connection",
|
||||
"segments/crystal",
|
||||
"segments/dart",
|
||||
"segments/deno",
|
||||
|
@ -110,7 +111,6 @@ module.exports = {
|
|||
"segments/time",
|
||||
"segments/ui5tooling",
|
||||
"segments/wakatime",
|
||||
"segments/wifi",
|
||||
"segments/withings",
|
||||
"segments/winreg",
|
||||
"segments/ytm",
|
||||
|
|
Loading…
Reference in a new issue