Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05eab972d7 | ||
|
|
eeddce7225 | ||
|
|
56aa0f7e5e | ||
|
|
86596461a1 | ||
|
|
cd57dbc770 | ||
|
|
f2c24bc0ec | ||
|
|
bd6aa31c4d | ||
|
|
f59ac30f51 | ||
|
|
4beda1639e | ||
|
|
7a133f3867 | ||
|
|
3f1adbe126 | ||
|
|
0d3f805a2d | ||
|
|
2855b9e612 | ||
|
|
217948ade6 | ||
|
|
c621d03a71 | ||
|
|
13efa0393c | ||
|
|
d5f81e9fd6 | ||
|
|
8f742709b6 | ||
|
|
40213ba5c3 | ||
|
|
deeb0dfbf0 | ||
|
|
ad013fb8f5 | ||
|
|
6def26ef02 | ||
|
|
a16816e862 | ||
|
|
cc6cc192cb | ||
|
|
f59b735f38 | ||
|
|
53c7fe292e | ||
|
|
fe0b0bf6dd | ||
|
|
8f3f6c77bd | ||
|
|
5750894336 | ||
|
|
63f1a142d8 | ||
|
|
9bea626f7c | ||
|
|
3f5704237a | ||
|
|
d9ce425981 | ||
|
|
069b09e5ec | ||
|
|
8f2afa0441 | ||
|
|
8fa1c6d596 | ||
|
|
12f4dc75f0 | ||
|
|
913fcc34ee | ||
|
|
ac856f4174 | ||
|
|
a5d793926b | ||
|
|
40a94bd001 | ||
|
|
d19836b821 | ||
|
|
32d865e24e |
740
.golangci.yml
740
.golangci.yml
@@ -14,23 +14,29 @@ linters:
|
||||
- contextcheck
|
||||
- decorder
|
||||
- durationcheck
|
||||
- err113
|
||||
- errcheck
|
||||
- errchkjson
|
||||
- errorlint
|
||||
- exptostd
|
||||
- ginkgolinter
|
||||
- gocheckcompilerdirectives
|
||||
- gocritic
|
||||
- godoclint
|
||||
- godot
|
||||
- godox
|
||||
- goprintffuncname
|
||||
- gosec
|
||||
- gosmopolitan
|
||||
- govet
|
||||
- grouper
|
||||
- importas
|
||||
- ineffassign
|
||||
- intrange
|
||||
- ireturn
|
||||
- makezero
|
||||
- mirror
|
||||
- misspell
|
||||
- modernize
|
||||
- nakedret
|
||||
- nilerr
|
||||
- nilnil
|
||||
@@ -38,6 +44,7 @@ linters:
|
||||
- noctx
|
||||
- nolintlint
|
||||
- nonamedreturns
|
||||
- perfsprint
|
||||
- predeclared
|
||||
- promlinter
|
||||
- reassign
|
||||
@@ -46,14 +53,731 @@ linters:
|
||||
- staticcheck
|
||||
- unconvert
|
||||
- unused
|
||||
- usestdlibvars
|
||||
- wastedassign
|
||||
- whitespace
|
||||
- wsl
|
||||
- wsl_v5
|
||||
settings:
|
||||
gosec:
|
||||
decorder:
|
||||
dec-order:
|
||||
- type
|
||||
- const
|
||||
- var
|
||||
- func
|
||||
gocritic:
|
||||
disable-all: false
|
||||
enable-all: true
|
||||
disabled-checks:
|
||||
- singleCaseSwitch
|
||||
- octalLiteral
|
||||
- regexpSimplify
|
||||
- paramTypeCombine
|
||||
- whyNoLint
|
||||
- hugeParam
|
||||
godoclint:
|
||||
default: all
|
||||
ignore-unexported: false
|
||||
ignore-exported: false
|
||||
include-unexported: true
|
||||
disable:
|
||||
- max-len
|
||||
godot:
|
||||
scope: all
|
||||
exclude:
|
||||
# Exclude todo and fixme comments.
|
||||
- "^fixme:"
|
||||
- "^todo:"
|
||||
period: true
|
||||
capital: false
|
||||
godox:
|
||||
keywords:
|
||||
- FIXME
|
||||
gosec: # go-fucking-sic
|
||||
excludes:
|
||||
- G404
|
||||
- G306
|
||||
# Боже, как же вы затрахали своей крипто-ебучкой, наркоманы хреновы!
|
||||
- G405 # Detect the usage of DES or RC4
|
||||
- G406 # Detect the usage of MD4 or RIPEMD160
|
||||
# Оно не используется для повышения безопасности или каких-то таких секъюрных вещей, оно используется для выборки
|
||||
# произвольного элемента из массива, так что ИДИ НАХУЙ с этой проверкой и не еби мозги липовой безопасностью.
|
||||
- G404 # Insecure random number source (rand)
|
||||
- G501 # Import blocklist: crypto/md5
|
||||
- G502 # Import blocklist: crypto/des
|
||||
- G503 # Import blocklist: crypto/rc4
|
||||
- G504 # Import blocklist: net/http/cgi
|
||||
- G505 # Import blocklist: crypto/sha1
|
||||
- G506 # Import blocklist: golang.org/x/crypto/md4
|
||||
- G507 # Import blocklist: golang.org/x/crypto/ripemd160
|
||||
config:
|
||||
global:
|
||||
audit: true
|
||||
# Ваша сраная паранойя при создании файлов и каталогов мешает нормальной работе сервисов. Группы придуманы для
|
||||
# удобства, группе удобно давать право чтения. Поэтому идите нахуй со своими ограничениями на чтение для
|
||||
# группы, "безопасные" клоуны.
|
||||
G301: "0755"
|
||||
G306: "0644"
|
||||
govet:
|
||||
disable-all: false
|
||||
enable-all: true
|
||||
disable:
|
||||
- shadow
|
||||
- fieldalignment
|
||||
grouper:
|
||||
# Require the use of a single global 'const' declaration only.
|
||||
# Default: false
|
||||
const-require-single-const: true
|
||||
# Require the use of grouped global 'const' declarations.
|
||||
# Default: false
|
||||
const-require-grouping: true
|
||||
# Require the use of a single 'import' declaration only.
|
||||
# Default: false
|
||||
import-require-single-import: true
|
||||
# Require the use of grouped 'import' declarations.
|
||||
# Default: false
|
||||
import-require-grouping: true
|
||||
# Require the use of a single global 'type' declaration only.
|
||||
# Default: false
|
||||
type-require-single-type: true
|
||||
# Require the use of grouped global 'type' declarations.
|
||||
# Default: false
|
||||
type-require-grouping: true
|
||||
# Require the use of a single global 'var' declaration only.
|
||||
# Default: false
|
||||
var-require-single-var: true
|
||||
# Require the use of grouped global 'var' declarations.
|
||||
# Default: false
|
||||
var-require-grouping: true
|
||||
misspell:
|
||||
# Correct spellings using locale preferences for US or UK.
|
||||
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
|
||||
# Default is to use a neutral variety of English.
|
||||
locale: US
|
||||
# Typos to ignore.
|
||||
# Should be in lower case.
|
||||
# Default: []
|
||||
ignore-rules:
|
||||
- someword
|
||||
# Extra word corrections.
|
||||
# `typo` and `correction` should only contain letters.
|
||||
# The words are case-insensitive.
|
||||
# Default: []
|
||||
extra-words:
|
||||
- typo: "iff"
|
||||
correction: "if"
|
||||
- typo: "cancelation"
|
||||
correction: "cancellation"
|
||||
# Mode of the analysis:
|
||||
# - default: checks all the file content.
|
||||
# - restricted: checks only comments.
|
||||
# Default: ""
|
||||
mode: restricted
|
||||
nonamedreturns:
|
||||
# Report named error if it is assigned inside defer.
|
||||
# Default: false
|
||||
report-error-in-defer: true
|
||||
perfsprint:
|
||||
integer-format: true
|
||||
int-conversion: true
|
||||
error-format: true
|
||||
err-error: false
|
||||
errorf: true
|
||||
string-format: true
|
||||
sprintf1: true
|
||||
strconcat: true
|
||||
bool-format: true
|
||||
hex-format: true
|
||||
concat-loop: true
|
||||
loop-other-ops: false
|
||||
revive:
|
||||
enable-all-rules: false
|
||||
staticcheck:
|
||||
# https://staticcheck.dev/docs/configuration/options/#dot_import_whitelist
|
||||
# Default: ["github.com/mmcloughlin/avo/build", "github.com/mmcloughlin/avo/operand", "github.com/mmcloughlin/avo/reg"]
|
||||
dot-import-whitelist:
|
||||
- fmt
|
||||
# https://staticcheck.dev/docs/configuration/options/#initialisms
|
||||
# Default: ["ACL", "API", "ASCII", "CPU", "CSS", "DNS", "EOF", "GUID", "HTML", "HTTP", "HTTPS", "ID", "IP", "JSON", "QPS", "RAM", "RPC", "SLA", "SMTP", "SQL", "SSH", "TCP", "TLS", "TTL", "UDP", "UI", "GID", "UID", "UUID", "URI", "URL", "UTF8", "VM", "XML", "XMPP", "XSRF", "XSS", "SIP", "RTP", "AMQP", "DB", "TS"]
|
||||
initialisms:
|
||||
[
|
||||
"ACL",
|
||||
"API",
|
||||
"ASCII",
|
||||
"CPU",
|
||||
"CSS",
|
||||
"DNS",
|
||||
"EOF",
|
||||
"GUID",
|
||||
"HTML",
|
||||
"HTTP",
|
||||
"HTTPS",
|
||||
"ID",
|
||||
"IP",
|
||||
"JSON",
|
||||
"QPS",
|
||||
"RAM",
|
||||
"RPC",
|
||||
"SLA",
|
||||
"SMTP",
|
||||
"SQL",
|
||||
"SSH",
|
||||
"TCP",
|
||||
"TLS",
|
||||
"TTL",
|
||||
"UDP",
|
||||
"UI",
|
||||
"GID",
|
||||
"UID",
|
||||
"UUID",
|
||||
"URI",
|
||||
"URL",
|
||||
"UTF8",
|
||||
"VM",
|
||||
"XML",
|
||||
"XMPP",
|
||||
"XSRF",
|
||||
"XSS",
|
||||
"SIP",
|
||||
"RTP",
|
||||
"AMQP",
|
||||
"DB",
|
||||
"TS",
|
||||
]
|
||||
# https://staticcheck.dev/docs/configuration/options/#http_status_code_whitelist
|
||||
# Default: ["200", "400", "404", "500"]
|
||||
http-status-code-whitelist: ["200", "400", "404", "500"]
|
||||
# SAxxxx checks in https://staticcheck.dev/docs/configuration/options/#checks
|
||||
# Example (to disable some checks): [ "all", "-SA1000", "-SA1001"]
|
||||
# Run `GL_DEBUG=staticcheck golangci-lint run --enable=staticcheck` to see all available checks and enabled by config checks.
|
||||
# Default: ["all", "-ST1000", "-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022"]
|
||||
checks:
|
||||
# Invalid regular expression.
|
||||
# https://staticcheck.dev/docs/checks/#SA1000
|
||||
- SA1000
|
||||
# Invalid template.
|
||||
# https://staticcheck.dev/docs/checks/#SA1001
|
||||
- SA1001
|
||||
# Invalid format in 'time.Parse'.
|
||||
# https://staticcheck.dev/docs/checks/#SA1002
|
||||
- SA1002
|
||||
# Unsupported argument to functions in 'encoding/binary'.
|
||||
# https://staticcheck.dev/docs/checks/#SA1003
|
||||
- SA1003
|
||||
# Suspiciously small untyped constant in 'time.Sleep'.
|
||||
# https://staticcheck.dev/docs/checks/#SA1004
|
||||
- SA1004
|
||||
# Invalid first argument to 'exec.Command'.
|
||||
# https://staticcheck.dev/docs/checks/#SA1005
|
||||
- SA1005
|
||||
# 'Printf' with dynamic first argument and no further arguments.
|
||||
# https://staticcheck.dev/docs/checks/#SA1006
|
||||
- SA1006
|
||||
# Invalid URL in 'net/url.Parse'.
|
||||
# https://staticcheck.dev/docs/checks/#SA1007
|
||||
- SA1007
|
||||
# Non-canonical key in 'http.Header' map.
|
||||
# https://staticcheck.dev/docs/checks/#SA1008
|
||||
- SA1008
|
||||
# '(*regexp.Regexp).FindAll' called with 'n == 0', which will always return zero results.
|
||||
# https://staticcheck.dev/docs/checks/#SA1010
|
||||
- SA1010
|
||||
# Various methods in the "strings" package expect valid UTF-8, but invalid input is provided.
|
||||
# https://staticcheck.dev/docs/checks/#SA1011
|
||||
- SA1011
|
||||
# A nil 'context.Context' is being passed to a function, consider using 'context.TODO' instead.
|
||||
# https://staticcheck.dev/docs/checks/#SA1012
|
||||
- SA1012
|
||||
# 'io.Seeker.Seek' is being called with the whence constant as the first argument, but it should be the second.
|
||||
# https://staticcheck.dev/docs/checks/#SA1013
|
||||
- SA1013
|
||||
# Non-pointer value passed to 'Unmarshal' or 'Decode'.
|
||||
# https://staticcheck.dev/docs/checks/#SA1014
|
||||
- SA1014
|
||||
# Using 'time.Tick' in a way that will leak. Consider using 'time.NewTicker', and only use 'time.Tick' in tests, commands and endless functions.
|
||||
# https://staticcheck.dev/docs/checks/#SA1015
|
||||
- SA1015
|
||||
# Trapping a signal that cannot be trapped.
|
||||
# https://staticcheck.dev/docs/checks/#SA1016
|
||||
- SA1016
|
||||
# Channels used with 'os/signal.Notify' should be buffered.
|
||||
# https://staticcheck.dev/docs/checks/#SA1017
|
||||
- SA1017
|
||||
# 'strings.Replace' called with 'n == 0', which does nothing.
|
||||
# https://staticcheck.dev/docs/checks/#SA1018
|
||||
- SA1018
|
||||
# Using a deprecated function, variable, constant or field.
|
||||
# https://staticcheck.dev/docs/checks/#SA1019
|
||||
- SA1019
|
||||
# Using an invalid host:port pair with a 'net.Listen'-related function.
|
||||
# https://staticcheck.dev/docs/checks/#SA1020
|
||||
- SA1020
|
||||
# Using 'bytes.Equal' to compare two 'net.IP'.
|
||||
# https://staticcheck.dev/docs/checks/#SA1021
|
||||
- SA1021
|
||||
# Modifying the buffer in an 'io.Writer' implementation.
|
||||
# https://staticcheck.dev/docs/checks/#SA1023
|
||||
- SA1023
|
||||
# A string cutset contains duplicate characters.
|
||||
# https://staticcheck.dev/docs/checks/#SA1024
|
||||
- SA1024
|
||||
# It is not possible to use '(*time.Timer).Reset''s return value correctly.
|
||||
# https://staticcheck.dev/docs/checks/#SA1025
|
||||
- SA1025
|
||||
# Cannot marshal channels or functions.
|
||||
# https://staticcheck.dev/docs/checks/#SA1026
|
||||
- SA1026
|
||||
# Atomic access to 64-bit variable must be 64-bit aligned.
|
||||
# https://staticcheck.dev/docs/checks/#SA1027
|
||||
- SA1027
|
||||
# 'sort.Slice' can only be used on slices.
|
||||
# https://staticcheck.dev/docs/checks/#SA1028
|
||||
- SA1028
|
||||
# Inappropriate key in call to 'context.WithValue'.
|
||||
# https://staticcheck.dev/docs/checks/#SA1029
|
||||
- SA1029
|
||||
# Invalid argument in call to a 'strconv' function.
|
||||
# https://staticcheck.dev/docs/checks/#SA1030
|
||||
- SA1030
|
||||
# Overlapping byte slices passed to an encoder.
|
||||
# https://staticcheck.dev/docs/checks/#SA1031
|
||||
- SA1031
|
||||
# Wrong order of arguments to 'errors.Is'.
|
||||
# https://staticcheck.dev/docs/checks/#SA1032
|
||||
- SA1032
|
||||
# 'sync.WaitGroup.Add' called inside the goroutine, leading to a race condition.
|
||||
# https://staticcheck.dev/docs/checks/#SA2000
|
||||
- SA2000
|
||||
# Empty critical section, did you mean to defer the unlock?.
|
||||
# https://staticcheck.dev/docs/checks/#SA2001
|
||||
- SA2001
|
||||
# Called 'testing.T.FailNow' or 'SkipNow' in a goroutine, which isn't allowed.
|
||||
# https://staticcheck.dev/docs/checks/#SA2002
|
||||
- SA2002
|
||||
# Deferred 'Lock' right after locking, likely meant to defer 'Unlock' instead.
|
||||
# https://staticcheck.dev/docs/checks/#SA2003
|
||||
- SA2003
|
||||
# 'TestMain' doesn't call 'os.Exit', hiding test failures.
|
||||
# https://staticcheck.dev/docs/checks/#SA3000
|
||||
- SA3000
|
||||
# Assigning to 'b.N' in benchmarks distorts the results.
|
||||
# https://staticcheck.dev/docs/checks/#SA3001
|
||||
- SA3001
|
||||
# Binary operator has identical expressions on both sides.
|
||||
# https://staticcheck.dev/docs/checks/#SA4000
|
||||
- SA4000
|
||||
# '&*x' gets simplified to 'x', it does not copy 'x'.
|
||||
# https://staticcheck.dev/docs/checks/#SA4001
|
||||
- SA4001
|
||||
# Comparing unsigned values against negative values is pointless.
|
||||
# https://staticcheck.dev/docs/checks/#SA4003
|
||||
- SA4003
|
||||
# The loop exits unconditionally after one iteration.
|
||||
# https://staticcheck.dev/docs/checks/#SA4004
|
||||
- SA4004
|
||||
# Field assignment that will never be observed. Did you mean to use a pointer receiver?.
|
||||
# https://staticcheck.dev/docs/checks/#SA4005
|
||||
- SA4005
|
||||
# A value assigned to a variable is never read before being overwritten. Forgotten error check or dead code?.
|
||||
# https://staticcheck.dev/docs/checks/#SA4006
|
||||
- SA4006
|
||||
# The variable in the loop condition never changes, are you incrementing the wrong variable?.
|
||||
# https://staticcheck.dev/docs/checks/#SA4008
|
||||
- SA4008
|
||||
# A function argument is overwritten before its first use.
|
||||
# https://staticcheck.dev/docs/checks/#SA4009
|
||||
- SA4009
|
||||
# The result of 'append' will never be observed anywhere.
|
||||
# https://staticcheck.dev/docs/checks/#SA4010
|
||||
- SA4010
|
||||
# Break statement with no effect. Did you mean to break out of an outer loop?.
|
||||
# https://staticcheck.dev/docs/checks/#SA4011
|
||||
- SA4011
|
||||
# Comparing a value against NaN even though no value is equal to NaN.
|
||||
# https://staticcheck.dev/docs/checks/#SA4012
|
||||
- SA4012
|
||||
# Negating a boolean twice ('!!b') is the same as writing 'b'. This is either redundant, or a typo.
|
||||
# https://staticcheck.dev/docs/checks/#SA4013
|
||||
- SA4013
|
||||
# An if/else if chain has repeated conditions and no side-effects; if the condition didn't match the first time, it won't match the second time, either.
|
||||
# https://staticcheck.dev/docs/checks/#SA4014
|
||||
- SA4014
|
||||
# Calling functions like 'math.Ceil' on floats converted from integers doesn't do anything useful.
|
||||
# https://staticcheck.dev/docs/checks/#SA4015
|
||||
- SA4015
|
||||
# Certain bitwise operations, such as 'x ^ 0', do not do anything useful.
|
||||
# https://staticcheck.dev/docs/checks/#SA4016
|
||||
- SA4016
|
||||
# Discarding the return values of a function without side effects, making the call pointless.
|
||||
# https://staticcheck.dev/docs/checks/#SA4017
|
||||
- SA4017
|
||||
# Self-assignment of variables.
|
||||
# https://staticcheck.dev/docs/checks/#SA4018
|
||||
- SA4018
|
||||
# Multiple, identical build constraints in the same file.
|
||||
# https://staticcheck.dev/docs/checks/#SA4019
|
||||
- SA4019
|
||||
# Unreachable case clause in a type switch.
|
||||
# https://staticcheck.dev/docs/checks/#SA4020
|
||||
- SA4020
|
||||
# "x = append(y)" is equivalent to "x = y".
|
||||
# https://staticcheck.dev/docs/checks/#SA4021
|
||||
- SA4021
|
||||
# Comparing the address of a variable against nil.
|
||||
# https://staticcheck.dev/docs/checks/#SA4022
|
||||
- SA4022
|
||||
# Impossible comparison of interface value with untyped nil.
|
||||
# https://staticcheck.dev/docs/checks/#SA4023
|
||||
- SA4023
|
||||
# Checking for impossible return value from a builtin function.
|
||||
# https://staticcheck.dev/docs/checks/#SA4024
|
||||
- SA4024
|
||||
# Integer division of literals that results in zero.
|
||||
# https://staticcheck.dev/docs/checks/#SA4025
|
||||
- SA4025
|
||||
# Go constants cannot express negative zero.
|
||||
# https://staticcheck.dev/docs/checks/#SA4026
|
||||
- SA4026
|
||||
# '(*net/url.URL).Query' returns a copy, modifying it doesn't change the URL.
|
||||
# https://staticcheck.dev/docs/checks/#SA4027
|
||||
- SA4027
|
||||
# 'x % 1' is always zero.
|
||||
# https://staticcheck.dev/docs/checks/#SA4028
|
||||
- SA4028
|
||||
# Ineffective attempt at sorting slice.
|
||||
# https://staticcheck.dev/docs/checks/#SA4029
|
||||
- SA4029
|
||||
# Ineffective attempt at generating random number.
|
||||
# https://staticcheck.dev/docs/checks/#SA4030
|
||||
- SA4030
|
||||
# Checking never-nil value against nil.
|
||||
# https://staticcheck.dev/docs/checks/#SA4031
|
||||
- SA4031
|
||||
# Comparing 'runtime.GOOS' or 'runtime.GOARCH' against impossible value.
|
||||
# https://staticcheck.dev/docs/checks/#SA4032
|
||||
- SA4032
|
||||
# Assignment to nil map.
|
||||
# https://staticcheck.dev/docs/checks/#SA5000
|
||||
- SA5000
|
||||
# Deferring 'Close' before checking for a possible error.
|
||||
# https://staticcheck.dev/docs/checks/#SA5001
|
||||
- SA5001
|
||||
# The empty for loop ("for {}") spins and can block the scheduler.
|
||||
# https://staticcheck.dev/docs/checks/#SA5002
|
||||
- SA5002
|
||||
# Defers in infinite loops will never execute.
|
||||
# https://staticcheck.dev/docs/checks/#SA5003
|
||||
- SA5003
|
||||
# "for { select { ..." with an empty default branch spins.
|
||||
# https://staticcheck.dev/docs/checks/#SA5004
|
||||
- SA5004
|
||||
# The finalizer references the finalized object, preventing garbage collection.
|
||||
# https://staticcheck.dev/docs/checks/#SA5005
|
||||
- SA5005
|
||||
# Infinite recursive call.
|
||||
# https://staticcheck.dev/docs/checks/#SA5007
|
||||
- SA5007
|
||||
# Invalid struct tag.
|
||||
# https://staticcheck.dev/docs/checks/#SA5008
|
||||
- SA5008
|
||||
# Invalid Printf call.
|
||||
# https://staticcheck.dev/docs/checks/#SA5009
|
||||
- SA5009
|
||||
# Impossible type assertion.
|
||||
# https://staticcheck.dev/docs/checks/#SA5010
|
||||
- SA5010
|
||||
# Possible nil pointer dereference.
|
||||
# https://staticcheck.dev/docs/checks/#SA5011
|
||||
- SA5011
|
||||
# Passing odd-sized slice to function expecting even size.
|
||||
# https://staticcheck.dev/docs/checks/#SA5012
|
||||
- SA5012
|
||||
# Using 'regexp.Match' or related in a loop, should use 'regexp.Compile'.
|
||||
# https://staticcheck.dev/docs/checks/#SA6000
|
||||
- SA6000
|
||||
# Missing an optimization opportunity when indexing maps by byte slices.
|
||||
# https://staticcheck.dev/docs/checks/#SA6001
|
||||
- SA6001
|
||||
# Storing non-pointer values in 'sync.Pool' allocates memory.
|
||||
# https://staticcheck.dev/docs/checks/#SA6002
|
||||
- SA6002
|
||||
# Converting a string to a slice of runes before ranging over it.
|
||||
# https://staticcheck.dev/docs/checks/#SA6003
|
||||
- SA6003
|
||||
# Inefficient string comparison with 'strings.ToLower' or 'strings.ToUpper'.
|
||||
# https://staticcheck.dev/docs/checks/#SA6005
|
||||
- SA6005
|
||||
# Using io.WriteString to write '[]byte'.
|
||||
# https://staticcheck.dev/docs/checks/#SA6006
|
||||
- SA6006
|
||||
# Defers in range loops may not run when you expect them to.
|
||||
# https://staticcheck.dev/docs/checks/#SA9001
|
||||
- SA9001
|
||||
# Using a non-octal 'os.FileMode' that looks like it was meant to be in octal.
|
||||
# https://staticcheck.dev/docs/checks/#SA9002
|
||||
- SA9002
|
||||
# Empty body in an if or else branch.
|
||||
# https://staticcheck.dev/docs/checks/#SA9003
|
||||
- SA9003
|
||||
# Only the first constant has an explicit type.
|
||||
# https://staticcheck.dev/docs/checks/#SA9004
|
||||
- SA9004
|
||||
# Trying to marshal a struct with no public fields nor custom marshaling.
|
||||
# https://staticcheck.dev/docs/checks/#SA9005
|
||||
- SA9005
|
||||
# Dubious bit shifting of a fixed size integer value.
|
||||
# https://staticcheck.dev/docs/checks/#SA9006
|
||||
- SA9006
|
||||
# Deleting a directory that shouldn't be deleted.
|
||||
# https://staticcheck.dev/docs/checks/#SA9007
|
||||
- SA9007
|
||||
# 'else' branch of a type assertion is probably not reading the right value.
|
||||
# https://staticcheck.dev/docs/checks/#SA9008
|
||||
- SA9008
|
||||
# Ineffectual Go compiler directive.
|
||||
# https://staticcheck.dev/docs/checks/#SA9009
|
||||
- SA9009
|
||||
# Incorrect or missing package comment.
|
||||
# https://staticcheck.dev/docs/checks/#ST1000
|
||||
- ST1000
|
||||
# Dot imports are discouraged.
|
||||
# https://staticcheck.dev/docs/checks/#ST1001
|
||||
- ST1001
|
||||
# Poorly chosen identifier.
|
||||
# https://staticcheck.dev/docs/checks/#ST1003
|
||||
- ST1003
|
||||
# Incorrectly formatted error string.
|
||||
# https://staticcheck.dev/docs/checks/#ST1005
|
||||
- ST1005
|
||||
# Poorly chosen receiver name.
|
||||
# https://staticcheck.dev/docs/checks/#ST1006
|
||||
- ST1006
|
||||
# A function's error value should be its last return value.
|
||||
# https://staticcheck.dev/docs/checks/#ST1008
|
||||
- ST1008
|
||||
# Poorly chosen name for variable of type 'time.Duration'.
|
||||
# https://staticcheck.dev/docs/checks/#ST1011
|
||||
- ST1011
|
||||
# Poorly chosen name for error variable.
|
||||
# https://staticcheck.dev/docs/checks/#ST1012
|
||||
- ST1012
|
||||
# Should use constants for HTTP error codes, not magic numbers.
|
||||
# https://staticcheck.dev/docs/checks/#ST1013
|
||||
- ST1013
|
||||
# A switch's default case should be the first or last case.
|
||||
# https://staticcheck.dev/docs/checks/#ST1015
|
||||
- ST1015
|
||||
# Use consistent method receiver names.
|
||||
# https://staticcheck.dev/docs/checks/#ST1016
|
||||
- ST1016
|
||||
# Don't use Yoda conditions.
|
||||
# https://staticcheck.dev/docs/checks/#ST1017
|
||||
- ST1017
|
||||
# Avoid zero-width and control characters in string literals.
|
||||
# https://staticcheck.dev/docs/checks/#ST1018
|
||||
- ST1018
|
||||
# Importing the same package multiple times.
|
||||
# https://staticcheck.dev/docs/checks/#ST1019
|
||||
- ST1019
|
||||
# The documentation of an exported function should start with the function's name.
|
||||
# https://staticcheck.dev/docs/checks/#ST1020
|
||||
- ST1020
|
||||
# The documentation of an exported type should start with type's name.
|
||||
# https://staticcheck.dev/docs/checks/#ST1021
|
||||
- ST1021
|
||||
# The documentation of an exported variable or constant should start with variable's name.
|
||||
# https://staticcheck.dev/docs/checks/#ST1022
|
||||
- ST1022
|
||||
# Redundant type in variable declaration.
|
||||
# https://staticcheck.dev/docs/checks/#ST1023
|
||||
- ST1023
|
||||
# Use plain channel send or receive instead of single-case select.
|
||||
# https://staticcheck.dev/docs/checks/#S1000
|
||||
- S1000
|
||||
# Replace for loop with call to copy.
|
||||
# https://staticcheck.dev/docs/checks/#S1001
|
||||
- S1001
|
||||
# Omit comparison with boolean constant.
|
||||
# https://staticcheck.dev/docs/checks/#S1002
|
||||
- S1002
|
||||
# Replace call to 'strings.Index' with 'strings.Contains'.
|
||||
# https://staticcheck.dev/docs/checks/#S1003
|
||||
- S1003
|
||||
# Replace call to 'bytes.Compare' with 'bytes.Equal'.
|
||||
# https://staticcheck.dev/docs/checks/#S1004
|
||||
- S1004
|
||||
# Drop unnecessary use of the blank identifier.
|
||||
# https://staticcheck.dev/docs/checks/#S1005
|
||||
- S1005
|
||||
# Use "for { ... }" for infinite loops.
|
||||
# https://staticcheck.dev/docs/checks/#S1006
|
||||
- S1006
|
||||
# Simplify regular expression by using raw string literal.
|
||||
# https://staticcheck.dev/docs/checks/#S1007
|
||||
- S1007
|
||||
# Simplify returning boolean expression.
|
||||
# https://staticcheck.dev/docs/checks/#S1008
|
||||
- S1008
|
||||
# Omit redundant nil check on slices, maps, and channels.
|
||||
# https://staticcheck.dev/docs/checks/#S1009
|
||||
- S1009
|
||||
# Omit default slice index.
|
||||
# https://staticcheck.dev/docs/checks/#S1010
|
||||
- S1010
|
||||
# Use a single 'append' to concatenate two slices.
|
||||
# https://staticcheck.dev/docs/checks/#S1011
|
||||
- S1011
|
||||
# Replace 'time.Now().Sub(x)' with 'time.Since(x)'.
|
||||
# https://staticcheck.dev/docs/checks/#S1012
|
||||
- S1012
|
||||
# Use a type conversion instead of manually copying struct fields.
|
||||
# https://staticcheck.dev/docs/checks/#S1016
|
||||
- S1016
|
||||
# Replace manual trimming with 'strings.TrimPrefix'.
|
||||
# https://staticcheck.dev/docs/checks/#S1017
|
||||
- S1017
|
||||
# Use "copy" for sliding elements.
|
||||
# https://staticcheck.dev/docs/checks/#S1018
|
||||
- S1018
|
||||
# Simplify "make" call by omitting redundant arguments.
|
||||
# https://staticcheck.dev/docs/checks/#S1019
|
||||
- S1019
|
||||
# Omit redundant nil check in type assertion.
|
||||
# https://staticcheck.dev/docs/checks/#S1020
|
||||
- S1020
|
||||
# Merge variable declaration and assignment.
|
||||
# https://staticcheck.dev/docs/checks/#S1021
|
||||
- S1021
|
||||
# Omit redundant control flow.
|
||||
# https://staticcheck.dev/docs/checks/#S1023
|
||||
- S1023
|
||||
# Replace 'x.Sub(time.Now())' with 'time.Until(x)'.
|
||||
# https://staticcheck.dev/docs/checks/#S1024
|
||||
- S1024
|
||||
# Don't use 'fmt.Sprintf("%s", x)' unnecessarily.
|
||||
# https://staticcheck.dev/docs/checks/#S1025
|
||||
- S1025
|
||||
# Simplify error construction with 'fmt.Errorf'.
|
||||
# https://staticcheck.dev/docs/checks/#S1028
|
||||
- S1028
|
||||
# Range over the string directly.
|
||||
# https://staticcheck.dev/docs/checks/#S1029
|
||||
- S1029
|
||||
# Use 'bytes.Buffer.String' or 'bytes.Buffer.Bytes'.
|
||||
# https://staticcheck.dev/docs/checks/#S1030
|
||||
- S1030
|
||||
# Omit redundant nil check around loop.
|
||||
# https://staticcheck.dev/docs/checks/#S1031
|
||||
- S1031
|
||||
# Use 'sort.Ints(x)', 'sort.Float64s(x)', and 'sort.Strings(x)'.
|
||||
# https://staticcheck.dev/docs/checks/#S1032
|
||||
- S1032
|
||||
# Unnecessary guard around call to "delete".
|
||||
# https://staticcheck.dev/docs/checks/#S1033
|
||||
- S1033
|
||||
# Use result of type assertion to simplify cases.
|
||||
# https://staticcheck.dev/docs/checks/#S1034
|
||||
- S1034
|
||||
# Redundant call to 'net/http.CanonicalHeaderKey' in method call on 'net/http.Header'.
|
||||
# https://staticcheck.dev/docs/checks/#S1035
|
||||
- S1035
|
||||
# Unnecessary guard around map access.
|
||||
# https://staticcheck.dev/docs/checks/#S1036
|
||||
- S1036
|
||||
# Elaborate way of sleeping.
|
||||
# https://staticcheck.dev/docs/checks/#S1037
|
||||
- S1037
|
||||
# Unnecessarily complex way of printing formatted string.
|
||||
# https://staticcheck.dev/docs/checks/#S1038
|
||||
- S1038
|
||||
# Unnecessary use of 'fmt.Sprint'.
|
||||
# https://staticcheck.dev/docs/checks/#S1039
|
||||
- S1039
|
||||
# Type assertion to current type.
|
||||
# https://staticcheck.dev/docs/checks/#S1040
|
||||
- S1040
|
||||
# Apply De Morgan's law.
|
||||
# https://staticcheck.dev/docs/checks/#QF1001
|
||||
- QF1001
|
||||
# Convert untagged switch to tagged switch.
|
||||
# https://staticcheck.dev/docs/checks/#QF1002
|
||||
- QF1002
|
||||
# Convert if/else-if chain to tagged switch.
|
||||
# https://staticcheck.dev/docs/checks/#QF1003
|
||||
- QF1003
|
||||
# Use 'strings.ReplaceAll' instead of 'strings.Replace' with 'n == -1'.
|
||||
# https://staticcheck.dev/docs/checks/#QF1004
|
||||
- QF1004
|
||||
# Expand call to 'math.Pow'.
|
||||
# https://staticcheck.dev/docs/checks/#QF1005
|
||||
- QF1005
|
||||
# Lift 'if'+'break' into loop condition.
|
||||
# https://staticcheck.dev/docs/checks/#QF1006
|
||||
- QF1006
|
||||
# Merge conditional assignment into variable declaration.
|
||||
# https://staticcheck.dev/docs/checks/#QF1007
|
||||
- QF1007
|
||||
# Omit embedded fields from selector expression.
|
||||
# https://staticcheck.dev/docs/checks/#QF1008
|
||||
- QF1008
|
||||
# Use 'time.Time.Equal' instead of '==' operator.
|
||||
# https://staticcheck.dev/docs/checks/#QF1009
|
||||
- QF1009
|
||||
# Convert slice of bytes to string when printing it.
|
||||
# https://staticcheck.dev/docs/checks/#QF1010
|
||||
- QF1010
|
||||
# Omit redundant type from variable declaration.
|
||||
# https://staticcheck.dev/docs/checks/#QF1011
|
||||
- QF1011
|
||||
# Use 'fmt.Fprintf(x, ...)' instead of 'x.Write(fmt.Sprintf(...))'.
|
||||
# https://staticcheck.dev/docs/checks/#QF1012
|
||||
- QF1012
|
||||
unconvert:
|
||||
# Remove conversions that force intermediate rounding.
|
||||
# Default: false
|
||||
fast-math: true
|
||||
# Be more conservative (experimental).
|
||||
# Default: false
|
||||
safe: true
|
||||
usestdlibvars:
|
||||
# Suggest the use of http.MethodXX.
|
||||
# Default: true
|
||||
http-method: false
|
||||
# Suggest the use of http.StatusXX.
|
||||
# Default: true
|
||||
http-status-code: false
|
||||
# Suggest the use of time.Month in time.Date.
|
||||
# Default: false
|
||||
time-date-month: true
|
||||
# Suggest the use of time.Weekday.String().
|
||||
# Default: true
|
||||
time-weekday: true
|
||||
# Suggest the use of time.Month.String().
|
||||
# Default: false
|
||||
time-month: true
|
||||
# Suggest the use of time.Layout.
|
||||
# Default: false
|
||||
time-layout: true
|
||||
# Suggest the use of crypto.Hash.String().
|
||||
# Default: false
|
||||
crypto-hash: true
|
||||
# Suggest the use of rpc.DefaultXXPath.
|
||||
# Default: false
|
||||
default-rpc-path: true
|
||||
# Suggest the use of sql.LevelXX.String().
|
||||
# Default: false
|
||||
sql-isolation-level: true
|
||||
# Suggest the use of tls.SignatureScheme.String().
|
||||
# Default: false
|
||||
tls-signature-scheme: true
|
||||
# Suggest the use of constant.Kind.String().
|
||||
# Default: false
|
||||
constant-kind: true
|
||||
wsl_v5:
|
||||
allow-first-in-block: true
|
||||
allow-whole-block: true
|
||||
branch-max-lines: 2
|
||||
case-max-lines: 2
|
||||
default: all
|
||||
disable:
|
||||
- if
|
||||
- err
|
||||
exclusions:
|
||||
generated: lax
|
||||
presets:
|
||||
@@ -62,8 +786,6 @@ linters:
|
||||
- legacy
|
||||
- std-error-handling
|
||||
paths:
|
||||
- data
|
||||
- vendor
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
@@ -74,8 +796,6 @@ formatters:
|
||||
exclusions:
|
||||
generated: lax
|
||||
paths:
|
||||
- data
|
||||
- vendor
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
|
||||
10
Makefile
10
Makefile
@@ -4,6 +4,7 @@ BUILDOPTS=-ldflags="-s -w" -a -gcflags=all=-l -trimpath -buildvcs=false
|
||||
|
||||
BINARY=i3status-go
|
||||
TEST1=battery-test
|
||||
TEST2=cmdrun-test
|
||||
|
||||
## Use calssic targets where first one is deafult target
|
||||
all: clean build
|
||||
@@ -16,15 +17,18 @@ battery-test:
|
||||
rm -rf ${TEST1}
|
||||
go build ${BUILDOPTS} -o ${TEST1} ./cmd/${TEST1}
|
||||
|
||||
cmdrun-test:
|
||||
rm -rf ${TEST1}
|
||||
go build ${BUILDOPTS} -o ${TEST2} ./cmd/${TEST2}
|
||||
|
||||
## Remove binary with golang compiler' means
|
||||
clean:
|
||||
rm -rf ${BINARY} ${TEST1}
|
||||
|
||||
rm -rf ${BINARY} ${TEST1} ${TEST2}
|
||||
|
||||
## Misc target, for development purposes. Updates vendored libs, brutal way.
|
||||
upgrade:
|
||||
$(RM) -r vendor
|
||||
go get -u -t -tool ./...
|
||||
go get -u -t ./...
|
||||
go mod tidy
|
||||
go mod vendor
|
||||
|
||||
|
||||
@@ -14,11 +14,12 @@ It is i3bar text generator.
|
||||
* PulseAudio volume indicator, can adjust master volume too
|
||||
* Clock
|
||||
* Cron jobs (intended to use for show periodic desktop notifications but not limited to)
|
||||
* Show output of one-shot system command
|
||||
|
||||
## How to build it
|
||||
|
||||
This appliction was tested to compile with go v1.21 but can be built with earlier versions (seems down to 1.18, not
|
||||
sure).
|
||||
This application was tested to compile with go v1.24.
|
||||
|
||||
All you need is go lang compiler and gnu make utility. Invoke
|
||||
|
||||
```bash
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Package main simple test for battery funtionality.
|
||||
package main
|
||||
|
||||
import (
|
||||
@@ -20,3 +21,5 @@ func main() {
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Default text and *block* border colors. If not set #3e78fd is used.
|
||||
"color" : "#3e78fd",
|
||||
|
||||
// Default backbround color. If not set value of #edeceb is used.
|
||||
// Default background color. If not set value of #edeceb is used.
|
||||
"background" : "#000000",
|
||||
|
||||
// Can be omitted, then Liberation Mono will be used.
|
||||
@@ -12,7 +12,7 @@
|
||||
// ‘smaller’ or ‘larger’
|
||||
"font_size": "medium",
|
||||
|
||||
"separator" : {
|
||||
"separator": {
|
||||
"left": {
|
||||
// Set to false if omitted.
|
||||
"enabled": true,
|
||||
@@ -702,10 +702,95 @@
|
||||
]
|
||||
},
|
||||
|
||||
// Prints stdout of command to panel.
|
||||
"cmdrun" : {
|
||||
"enabled": false,
|
||||
|
||||
// Delay between two consecutive command batch runs.
|
||||
"delay": 3,
|
||||
|
||||
// command' binary.
|
||||
"cmd": "/bin/bash",
|
||||
|
||||
// Arguments for command binary.
|
||||
"args": ["-c", "echo 42"],
|
||||
|
||||
// If omitted set to default color defined up here.
|
||||
"color": "#3e78fd",
|
||||
|
||||
// If omitted set to default background color defined up here.
|
||||
"background": "#000000",
|
||||
|
||||
// If omitted set to default font defined up here.
|
||||
"font": "Noto Sans",
|
||||
|
||||
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
|
||||
// ‘smaller’ or ‘larger’. If omitted set to default font size defined up here.
|
||||
"font_size": "medium",
|
||||
|
||||
// Re-define separator parameters for each command block here.
|
||||
"separator": {
|
||||
"left": {
|
||||
// Set to false if omitted.
|
||||
"enabled": true,
|
||||
|
||||
// If omitted set to default color defined for separator up here.
|
||||
"color": "#3e78fd",
|
||||
|
||||
// If omitted set to default background color defined for separator up here.
|
||||
"background": "#000000",
|
||||
|
||||
// If omitted set to default symbol defined for separator up here.
|
||||
"symbol": "▶",
|
||||
|
||||
// If omitted set to default font defined for separator up here.
|
||||
"font": "Noto Sans",
|
||||
|
||||
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
|
||||
// ‘smaller’ or ‘larger’. If omitted set to default font size defined for separator up here.
|
||||
"font_size": "medium"
|
||||
},
|
||||
|
||||
"right": {
|
||||
// Set to false if omitted.
|
||||
"enabled": true,
|
||||
|
||||
// If omitted set to default color defined for separator up here.
|
||||
"color": "#3e78fd",
|
||||
|
||||
// If omitted set to default background color defined for separator up here.
|
||||
"background": "#000000",
|
||||
|
||||
// If omitted set to default symbol defined for separator up here.
|
||||
"symbol": "◀",
|
||||
|
||||
// If omitted set to default font defined for separator up here.
|
||||
"font": "Noto Sans",
|
||||
|
||||
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
|
||||
// ‘smaller’ or ‘larger’. If omitted set to default font size defined for separator up here.
|
||||
"font_size": "medium"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Whether to display Application Buttons.
|
||||
"app_buttons": {
|
||||
"enabled": true,
|
||||
|
||||
// If omitted set to default color defined up here.
|
||||
"color": "#3e78fd",
|
||||
|
||||
// If omitted set to default background color defined up here.
|
||||
"background": "#000000",
|
||||
|
||||
// If omitted set to default font defined up here.
|
||||
"font": "Noto Sans",
|
||||
|
||||
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
|
||||
// ‘smaller’ or ‘larger’. If omitted set to default font size defined up here.
|
||||
"font_size": "medium",
|
||||
|
||||
// Re-define separator parameters for net-if block here.
|
||||
"separator": {
|
||||
"left": {
|
||||
@@ -749,31 +834,36 @@
|
||||
// ‘smaller’ or ‘larger’. If omitted set to default font size defined for separator up here.
|
||||
"font_size": "medium"
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
// Buttons - application launch "buttons"
|
||||
"apps": [
|
||||
{
|
||||
// Text dispalyed on button
|
||||
// Text displayed on button, pango markup supported.
|
||||
"full_text" : "📂",
|
||||
// Internal name, can be any string, but unique for each app button
|
||||
// Internal name, can be any string, but unique for each app button.
|
||||
"name" : "thunar",
|
||||
// Command itself
|
||||
// Command itself.
|
||||
"cmd" : "thunar",
|
||||
// Array of command args, optional
|
||||
// Array of command args, optional.
|
||||
"args": [ "." ],
|
||||
// Regexp that match with Instance component of WM_CLASS(STRING) of xprop output
|
||||
// Regexp that match with Instance component of WM_CLASS(STRING) of xprop output.
|
||||
"instance": "^thunar$",
|
||||
// Regexp that match with Class component of WM_CLASS(STRING) of xprop output
|
||||
// Regexp that match with Class component of WM_CLASS(STRING) of xprop output.
|
||||
"class": "^Thunar$",
|
||||
// text color in html notation
|
||||
// Text color in html notation.
|
||||
"color": "#ffa500",
|
||||
// background color in html notation
|
||||
// background color in html notation.
|
||||
"background" : "#000000",
|
||||
// border color in html notation
|
||||
// If omitted set to default font defined for app_buttons up here.
|
||||
"font": "Noto Sans",
|
||||
// ‘xx-small’, ‘x-small’, ‘small’, ‘medium’, ‘large’, ‘x-large’, ‘xx-large’, or one of relative sizes
|
||||
// ‘smaller’ or ‘larger’. If omitted set to default font size defined for app_buttons up here.
|
||||
"font_size": "medium",
|
||||
// Border color in html notation.
|
||||
"border": "#666666",
|
||||
// border color if there is at least one window with given Instance and/or Class exist
|
||||
// Border color if there is at least one window with given Instance and/or Class exist.
|
||||
"border_active": "#3e78fd",
|
||||
// Vertical line between objects on bar - if omitted true value is assumed by i3bar, but we set it to false
|
||||
// in that case. It is limitation of golang json parser.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Package main status string generator for i3bar.
|
||||
package main
|
||||
|
||||
import (
|
||||
@@ -8,6 +9,7 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
@@ -15,7 +17,7 @@ import (
|
||||
)
|
||||
|
||||
//go:embed default-config.json
|
||||
var DefaultConfig []byte
|
||||
var DefaultConfig []byte //nolint: godoclint, grouper, nolintlint
|
||||
|
||||
// Program entry point.
|
||||
func main() {
|
||||
@@ -42,15 +44,11 @@ func main() {
|
||||
// Conf.Values.PA
|
||||
Conf.Values.SoundVolume = "🔊:0%"
|
||||
|
||||
// TODO: Проставить дефолтные значения для глобальных переменных модулей.
|
||||
Conf.Values.BatteryString = fmt.Sprintf(
|
||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
||||
Conf.Battery.Color,
|
||||
Conf.Battery.Background,
|
||||
Conf.Battery.SymbolFont,
|
||||
Conf.Battery.SymbolFontSize,
|
||||
Conf.Battery.Symbol,
|
||||
)
|
||||
Conf.Values.BatteryString = "<span color='" + Conf.Battery.Color +
|
||||
"' background='" + Conf.Battery.Background +
|
||||
"' font='" + Conf.Battery.SymbolFont +
|
||||
"' size='" + Conf.Battery.SymbolFontSize +
|
||||
"'>" + Conf.Battery.Symbol + "</span>"
|
||||
|
||||
Conf.Values.BatteryString += fmt.Sprintf(
|
||||
"<span color='%s' background='%s' font='%s' size='%s'> ??%% •</span>",
|
||||
@@ -84,6 +82,14 @@ func main() {
|
||||
Conf.Clock.FontSize,
|
||||
)
|
||||
|
||||
Conf.Values.RunCommandOutput = fmt.Sprintf(
|
||||
"<span color='%s' background='%s' font='%s' size='%s'>?</span>",
|
||||
Conf.CmdRun.Color,
|
||||
Conf.CmdRun.Background,
|
||||
Conf.CmdRun.Font,
|
||||
Conf.CmdRun.FontSize,
|
||||
)
|
||||
|
||||
go Conf.Spawner()
|
||||
go Conf.ParseStdin()
|
||||
go Conf.CleanZombies()
|
||||
@@ -96,6 +102,7 @@ func main() {
|
||||
|
||||
// Kick signal handler
|
||||
go Conf.SigHandler()
|
||||
|
||||
signal.Notify(Conf.Channels.SigChan,
|
||||
syscall.SIGUSR1,
|
||||
syscall.SIGUSR2,
|
||||
@@ -143,6 +150,10 @@ func main() {
|
||||
go Conf.UpdateVPNStatus()
|
||||
}
|
||||
|
||||
if Conf.CmdRun.Enabled {
|
||||
go Conf.RunCommand()
|
||||
}
|
||||
|
||||
/*
|
||||
I3bar documentation pretends that message protocol must be valid json. In practice, we only have to print valid
|
||||
header, empty json array and (potentially infinite) json lines (line that is valid json by itself) that is
|
||||
@@ -166,33 +177,10 @@ func main() {
|
||||
|
||||
// TODO: впилить для первого и последнего батона separator
|
||||
if Conf.AppButtons.Enabled {
|
||||
for num, app := range Conf.Apps {
|
||||
for _, app := range Conf.Apps {
|
||||
var b lib.I3BarOutBlock
|
||||
|
||||
if num == 0 {
|
||||
b.FullText = fmt.Sprintf(
|
||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
||||
Conf.AppButtons.Separator.Left.Color,
|
||||
Conf.AppButtons.Separator.Left.Background,
|
||||
Conf.AppButtons.Separator.Left.Font,
|
||||
Conf.AppButtons.Separator.Left.FontSize,
|
||||
Conf.AppButtons.Separator.Left.Symbol,
|
||||
)
|
||||
}
|
||||
|
||||
b.FullText = app.FullText
|
||||
|
||||
if num == len(Conf.Apps) {
|
||||
b.FullText = fmt.Sprintf(
|
||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
||||
Conf.AppButtons.Separator.Right.Color,
|
||||
Conf.AppButtons.Separator.Right.Background,
|
||||
Conf.AppButtons.Separator.Right.Font,
|
||||
Conf.AppButtons.Separator.Right.FontSize,
|
||||
Conf.AppButtons.Separator.Right.Symbol,
|
||||
)
|
||||
}
|
||||
|
||||
b.Background = app.Background
|
||||
b.Color = app.Color
|
||||
b.Instance = app.Instance
|
||||
@@ -217,42 +205,55 @@ func main() {
|
||||
}
|
||||
|
||||
if Conf.CPUTemp.Enabled {
|
||||
var b lib.I3BarOutBlock
|
||||
var (
|
||||
b lib.I3BarOutBlock
|
||||
sb strings.Builder
|
||||
)
|
||||
|
||||
b.Color = Conf.CPUTemp.Color
|
||||
b.Background = Conf.CPUTemp.Background
|
||||
|
||||
if Conf.CPUTemp.Separator.Left.Enabled {
|
||||
b.FullText = fmt.Sprintf(
|
||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
||||
Conf.CPUTemp.Separator.Left.Color,
|
||||
Conf.CPUTemp.Separator.Left.Background,
|
||||
Conf.CPUTemp.Separator.Left.Font,
|
||||
Conf.CPUTemp.Separator.Left.FontSize,
|
||||
Conf.CPUTemp.Separator.Left.Symbol,
|
||||
)
|
||||
sb.WriteString("<span color='")
|
||||
sb.WriteString(Conf.CPUTemp.Separator.Left.Color)
|
||||
sb.WriteString("' background='")
|
||||
sb.WriteString(Conf.CPUTemp.Separator.Left.Background)
|
||||
sb.WriteString("' font='")
|
||||
sb.WriteString(Conf.CPUTemp.Separator.Left.Font)
|
||||
sb.WriteString("' size='")
|
||||
sb.WriteString(Conf.CPUTemp.Separator.Left.FontSize)
|
||||
sb.WriteString("'>")
|
||||
sb.WriteString(Conf.CPUTemp.Separator.Left.Symbol)
|
||||
sb.WriteString("</span>")
|
||||
}
|
||||
|
||||
b.FullText += fmt.Sprintf(
|
||||
"<span color='%s' background='%s' font='%s' size='%s'>CPU: %d°</span>",
|
||||
Conf.CPUTemp.Color,
|
||||
Conf.CPUTemp.Background,
|
||||
Conf.CPUTemp.Font,
|
||||
Conf.CPUTemp.FontSize,
|
||||
Conf.Values.CPUTemperature,
|
||||
)
|
||||
sb.WriteString("<span color='")
|
||||
sb.WriteString(Conf.CPUTemp.Color)
|
||||
sb.WriteString("' background='")
|
||||
sb.WriteString(Conf.CPUTemp.Background)
|
||||
sb.WriteString("' font='")
|
||||
sb.WriteString(Conf.CPUTemp.Font)
|
||||
sb.WriteString("' size='")
|
||||
sb.WriteString(Conf.CPUTemp.FontSize)
|
||||
sb.WriteString("'>CPU: ")
|
||||
sb.WriteString(strconv.FormatInt(Conf.Values.CPUTemperature, 10))
|
||||
sb.WriteString("°</span>")
|
||||
|
||||
if Conf.CPUTemp.Separator.Right.Enabled {
|
||||
b.FullText += fmt.Sprintf(
|
||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
||||
Conf.CPUTemp.Separator.Right.Color,
|
||||
Conf.CPUTemp.Separator.Right.Background,
|
||||
Conf.CPUTemp.Separator.Right.Font,
|
||||
Conf.CPUTemp.Separator.Right.FontSize,
|
||||
Conf.CPUTemp.Separator.Right.Symbol,
|
||||
)
|
||||
sb.WriteString("<span color='")
|
||||
sb.WriteString(Conf.CPUTemp.Separator.Right.Color)
|
||||
sb.WriteString("' background='")
|
||||
sb.WriteString(Conf.CPUTemp.Separator.Right.Background)
|
||||
sb.WriteString("' font='")
|
||||
sb.WriteString(Conf.CPUTemp.Separator.Right.Font)
|
||||
sb.WriteString("' size='")
|
||||
sb.WriteString(Conf.CPUTemp.Separator.Right.FontSize)
|
||||
sb.WriteString("'>")
|
||||
sb.WriteString(Conf.CPUTemp.Separator.Right.Symbol)
|
||||
sb.WriteString("</span>")
|
||||
}
|
||||
|
||||
b.FullText = sb.String()
|
||||
b.Markup = "pango"
|
||||
b.Separator = false
|
||||
|
||||
@@ -260,56 +261,66 @@ func main() {
|
||||
}
|
||||
|
||||
if Conf.Mem.Enabled {
|
||||
var b lib.I3BarOutBlock
|
||||
var (
|
||||
b lib.I3BarOutBlock
|
||||
sb strings.Builder
|
||||
)
|
||||
|
||||
b.Color = Conf.Mem.Color
|
||||
b.Background = Conf.Mem.Background
|
||||
|
||||
if Conf.Mem.Separator.Left.Enabled {
|
||||
b.FullText = fmt.Sprintf(
|
||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
||||
Conf.Mem.Separator.Left.Color,
|
||||
Conf.Mem.Separator.Left.Background,
|
||||
Conf.Mem.Separator.Left.Font,
|
||||
Conf.Mem.Separator.Left.FontSize,
|
||||
Conf.Mem.Separator.Left.Symbol,
|
||||
)
|
||||
sb.WriteString("<span color='")
|
||||
sb.WriteString(Conf.Mem.Separator.Left.Color)
|
||||
sb.WriteString("' background='")
|
||||
sb.WriteString(Conf.Mem.Separator.Left.Background)
|
||||
sb.WriteString("' font='")
|
||||
sb.WriteString(Conf.Mem.Separator.Left.Font)
|
||||
sb.WriteString("' size='")
|
||||
sb.WriteString(Conf.Mem.Separator.Left.FontSize)
|
||||
sb.WriteString("'>")
|
||||
sb.WriteString(Conf.Mem.Separator.Left.Symbol)
|
||||
sb.WriteString("</span>")
|
||||
}
|
||||
|
||||
sb.WriteString("<span color='")
|
||||
sb.WriteString(Conf.Mem.Color)
|
||||
sb.WriteString("' background='")
|
||||
sb.WriteString(Conf.Mem.Background)
|
||||
sb.WriteString("' font='")
|
||||
sb.WriteString(Conf.Mem.Font)
|
||||
sb.WriteString("' size='")
|
||||
sb.WriteString(Conf.Mem.FontSize)
|
||||
sb.WriteString("'>M:")
|
||||
sb.WriteString(strconv.FormatUint(Conf.Values.Memory.Usedpct, 10))
|
||||
sb.WriteString("% SHM:")
|
||||
sb.WriteString(strconv.FormatUint(Conf.Values.Memory.Shared, 10))
|
||||
|
||||
if Conf.Mem.ShowSwap {
|
||||
b.FullText += fmt.Sprintf(
|
||||
"<span color='%s' background='%s' font='%s' size='%s'>M:%d%% SHM:%dM SW:%dM</span>",
|
||||
Conf.Mem.Color,
|
||||
Conf.Mem.Background,
|
||||
Conf.Mem.Font,
|
||||
Conf.Mem.FontSize,
|
||||
Conf.Values.Memory.Usedpct,
|
||||
Conf.Values.Memory.Shared,
|
||||
Conf.Values.Memory.Swap,
|
||||
)
|
||||
sb.WriteString("% SW:")
|
||||
sb.WriteString(strconv.FormatUint(Conf.Values.Memory.Swap, 10))
|
||||
sb.WriteString("M")
|
||||
} else {
|
||||
b.FullText += fmt.Sprintf(
|
||||
"<span color='%s' background='%s' font='%s' size='%s'>M:%d%% SHM:%dM</span>",
|
||||
Conf.Mem.Color,
|
||||
Conf.Mem.Background,
|
||||
Conf.Mem.Font,
|
||||
Conf.Mem.FontSize,
|
||||
Conf.Values.Memory.Usedpct,
|
||||
Conf.Values.Memory.Shared,
|
||||
)
|
||||
sb.WriteString("%")
|
||||
}
|
||||
|
||||
sb.WriteString("</span>")
|
||||
|
||||
if Conf.Mem.Separator.Right.Enabled {
|
||||
b.FullText += fmt.Sprintf(
|
||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
||||
Conf.Mem.Separator.Right.Color,
|
||||
Conf.Mem.Separator.Right.Background,
|
||||
Conf.Mem.Separator.Right.Font,
|
||||
Conf.Mem.Separator.Right.FontSize,
|
||||
Conf.Mem.Separator.Right.Symbol,
|
||||
)
|
||||
sb.WriteString("<span color='")
|
||||
sb.WriteString(Conf.Mem.Separator.Right.Color)
|
||||
sb.WriteString("' background='")
|
||||
sb.WriteString(Conf.Mem.Separator.Right.Background)
|
||||
sb.WriteString("' font='")
|
||||
sb.WriteString(Conf.Mem.Separator.Right.Font)
|
||||
sb.WriteString("' size='")
|
||||
sb.WriteString(Conf.Mem.Separator.Right.FontSize)
|
||||
sb.WriteString("'>")
|
||||
sb.WriteString(Conf.Mem.Separator.Right.Symbol)
|
||||
sb.WriteString("</span>")
|
||||
}
|
||||
|
||||
b.FullText = sb.String()
|
||||
b.Markup = "pango"
|
||||
b.Separator = false
|
||||
|
||||
@@ -317,42 +328,55 @@ func main() {
|
||||
}
|
||||
|
||||
if Conf.LA.Enabled {
|
||||
var b lib.I3BarOutBlock
|
||||
var (
|
||||
b lib.I3BarOutBlock
|
||||
sb strings.Builder
|
||||
)
|
||||
|
||||
b.Color = Conf.LA.Color
|
||||
b.Background = Conf.LA.Background
|
||||
|
||||
if Conf.LA.Separator.Left.Enabled {
|
||||
b.FullText = fmt.Sprintf(
|
||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
||||
Conf.LA.Separator.Left.Color,
|
||||
Conf.LA.Separator.Left.Background,
|
||||
Conf.LA.Separator.Left.Font,
|
||||
Conf.LA.Separator.Left.FontSize,
|
||||
Conf.LA.Separator.Left.Symbol,
|
||||
)
|
||||
sb.WriteString("<span color='")
|
||||
sb.WriteString(Conf.LA.Separator.Left.Color)
|
||||
sb.WriteString("' background='")
|
||||
sb.WriteString(Conf.LA.Separator.Left.Background)
|
||||
sb.WriteString("' font='")
|
||||
sb.WriteString(Conf.LA.Separator.Left.Font)
|
||||
sb.WriteString("' size='")
|
||||
sb.WriteString(Conf.LA.Separator.Left.FontSize)
|
||||
sb.WriteString("'>")
|
||||
sb.WriteString(Conf.LA.Separator.Left.Symbol)
|
||||
sb.WriteString("</span>")
|
||||
}
|
||||
|
||||
b.FullText += fmt.Sprintf(
|
||||
"<span color='%s' background='%s' font='%s' size='%s'>LA:%s</span>",
|
||||
Conf.LA.Color,
|
||||
Conf.LA.Background,
|
||||
Conf.LA.Font,
|
||||
Conf.LA.FontSize,
|
||||
Conf.Values.La,
|
||||
)
|
||||
sb.WriteString("<span color='")
|
||||
sb.WriteString(Conf.LA.Color)
|
||||
sb.WriteString("' background='")
|
||||
sb.WriteString(Conf.LA.Background)
|
||||
sb.WriteString("' font='")
|
||||
sb.WriteString(Conf.LA.Font)
|
||||
sb.WriteString("' size='")
|
||||
sb.WriteString(Conf.LA.FontSize)
|
||||
sb.WriteString("'>LA:")
|
||||
sb.WriteString(Conf.Values.La)
|
||||
sb.WriteString("</span>")
|
||||
|
||||
if Conf.LA.Separator.Right.Enabled {
|
||||
b.FullText += fmt.Sprintf(
|
||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
||||
Conf.LA.Separator.Right.Color,
|
||||
Conf.LA.Separator.Right.Background,
|
||||
Conf.LA.Separator.Right.Font,
|
||||
Conf.LA.Separator.Right.FontSize,
|
||||
Conf.LA.Separator.Right.Symbol,
|
||||
)
|
||||
sb.WriteString("<span color='")
|
||||
sb.WriteString(Conf.LA.Separator.Right.Color)
|
||||
sb.WriteString("' background='")
|
||||
sb.WriteString(Conf.LA.Separator.Right.Background)
|
||||
sb.WriteString("' font='")
|
||||
sb.WriteString(Conf.LA.Separator.Right.Font)
|
||||
sb.WriteString("' size='")
|
||||
sb.WriteString(Conf.LA.Separator.Right.FontSize)
|
||||
sb.WriteString("'>")
|
||||
sb.WriteString(Conf.LA.Separator.Right.Symbol)
|
||||
sb.WriteString("</span>")
|
||||
}
|
||||
|
||||
b.FullText = sb.String()
|
||||
b.Markup = "pango"
|
||||
b.Separator = false
|
||||
|
||||
@@ -519,44 +543,101 @@ func main() {
|
||||
j = append(j, b)
|
||||
}
|
||||
|
||||
if Conf.Clock.Enabled {
|
||||
if Conf.CmdRun.Enabled {
|
||||
var b lib.I3BarOutBlock
|
||||
|
||||
b.Name = `runcommandoutput`
|
||||
b.Color = Conf.CmdRun.Color
|
||||
b.Background = Conf.CmdRun.Background
|
||||
|
||||
if Conf.CmdRun.Separator.Left.Enabled {
|
||||
b.FullText = fmt.Sprintf(
|
||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
||||
Conf.CmdRun.Separator.Left.Color,
|
||||
Conf.CmdRun.Separator.Left.Background,
|
||||
Conf.CmdRun.Separator.Left.Font,
|
||||
Conf.CmdRun.Separator.Left.FontSize,
|
||||
Conf.CmdRun.Separator.Left.Symbol,
|
||||
)
|
||||
}
|
||||
|
||||
b.FullText += fmt.Sprintf(
|
||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
||||
Conf.CmdRun.Color,
|
||||
Conf.CmdRun.Background,
|
||||
Conf.CmdRun.Font,
|
||||
Conf.CmdRun.FontSize,
|
||||
Conf.Values.RunCommandOutput,
|
||||
)
|
||||
|
||||
if Conf.CmdRun.Separator.Right.Enabled {
|
||||
b.FullText += fmt.Sprintf(
|
||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
||||
Conf.CmdRun.Separator.Right.Color,
|
||||
Conf.CmdRun.Separator.Right.Background,
|
||||
Conf.CmdRun.Separator.Right.Font,
|
||||
Conf.CmdRun.Separator.Right.FontSize,
|
||||
Conf.CmdRun.Separator.Right.Symbol,
|
||||
)
|
||||
}
|
||||
|
||||
b.Markup = "pango"
|
||||
b.Separator = false
|
||||
|
||||
j = append(j, b)
|
||||
}
|
||||
|
||||
if Conf.Clock.Enabled {
|
||||
var (
|
||||
b lib.I3BarOutBlock
|
||||
sb strings.Builder
|
||||
)
|
||||
|
||||
b.Name = `wallclock`
|
||||
b.Color = Conf.Clock.Color
|
||||
b.Background = Conf.Clock.Background
|
||||
|
||||
if Conf.Clock.Separator.Left.Enabled {
|
||||
b.FullText = fmt.Sprintf(
|
||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
||||
Conf.Clock.Separator.Left.Color,
|
||||
Conf.Clock.Separator.Left.Background,
|
||||
Conf.Clock.Separator.Left.Font,
|
||||
Conf.Clock.Separator.Left.FontSize,
|
||||
Conf.Clock.Separator.Left.Symbol,
|
||||
)
|
||||
sb.WriteString("<span color='")
|
||||
sb.WriteString(Conf.Clock.Separator.Left.Color)
|
||||
sb.WriteString("' background='")
|
||||
sb.WriteString(Conf.Clock.Separator.Left.Background)
|
||||
sb.WriteString("' font='")
|
||||
sb.WriteString(Conf.Clock.Separator.Left.Font)
|
||||
sb.WriteString("' size='")
|
||||
sb.WriteString(Conf.Clock.Separator.Left.FontSize)
|
||||
sb.WriteString("'>")
|
||||
sb.WriteString(Conf.Clock.Separator.Left.Symbol)
|
||||
sb.WriteString("</span>")
|
||||
}
|
||||
|
||||
b.FullText += fmt.Sprintf(
|
||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
||||
Conf.Clock.Color,
|
||||
Conf.Clock.Background,
|
||||
Conf.Clock.Font,
|
||||
Conf.Clock.FontSize,
|
||||
Conf.Values.ClockTime,
|
||||
)
|
||||
sb.WriteString("<span color='")
|
||||
sb.WriteString(Conf.Clock.Color)
|
||||
sb.WriteString("' background='")
|
||||
sb.WriteString(Conf.Clock.Background)
|
||||
sb.WriteString("' font='")
|
||||
sb.WriteString(Conf.Clock.Font)
|
||||
sb.WriteString("' size='")
|
||||
sb.WriteString(Conf.Clock.FontSize)
|
||||
sb.WriteString("'>")
|
||||
sb.WriteString(Conf.Values.ClockTime)
|
||||
sb.WriteString("</span>")
|
||||
|
||||
if Conf.Clock.Separator.Right.Enabled {
|
||||
b.FullText += fmt.Sprintf(
|
||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
||||
Conf.Clock.Separator.Right.Color,
|
||||
Conf.Clock.Separator.Right.Background,
|
||||
Conf.Clock.Separator.Right.Font,
|
||||
Conf.Clock.Separator.Right.FontSize,
|
||||
Conf.Clock.Separator.Right.Symbol,
|
||||
)
|
||||
sb.WriteString("<span color='")
|
||||
sb.WriteString(Conf.Clock.Separator.Right.Color)
|
||||
sb.WriteString("' background='")
|
||||
sb.WriteString(Conf.Clock.Separator.Right.Background)
|
||||
sb.WriteString("' font='")
|
||||
sb.WriteString(Conf.Clock.Separator.Right.Font)
|
||||
sb.WriteString("' size='")
|
||||
sb.WriteString(Conf.Clock.Separator.Right.FontSize)
|
||||
sb.WriteString("'>")
|
||||
sb.WriteString(Conf.Clock.Separator.Right.Symbol)
|
||||
sb.WriteString("</span>")
|
||||
}
|
||||
|
||||
b.FullText = sb.String()
|
||||
b.Markup = "pango"
|
||||
b.Separator = false
|
||||
|
||||
@@ -585,3 +666,5 @@ func PrintToI3bar(c *lib.MyConfig) {
|
||||
fmt.Println(strings.TrimSuffix(buf.String(), "\n") + ",")
|
||||
}
|
||||
}
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
|
||||
@@ -1 +1 @@
|
||||
/home/eleksir/git/i3status-go/cmd/i3status-go/default-config.json
|
||||
../cmd/i3status-go/default-config.json
|
||||
@@ -1,3 +1,4 @@
|
||||
// Package lib represents guts of i3status-go.
|
||||
package lib
|
||||
|
||||
import (
|
||||
@@ -29,7 +30,7 @@ func (c *MyConfig) UpdateBatteryInfo() {
|
||||
}
|
||||
|
||||
var (
|
||||
batteries []*battery.Battery = []*battery.Battery{}
|
||||
batteries = []*battery.Battery{}
|
||||
Batts string
|
||||
ch int
|
||||
status string
|
||||
@@ -52,23 +53,26 @@ func (c *MyConfig) UpdateBatteryInfo() {
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Unable to read file %s: %s", file, err)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
myCharge = strings.Trim(string(b), "\n")
|
||||
myCharge = strings.TrimSpace(string(b))
|
||||
|
||||
statusFile := filepath.Dir(file) + "/status"
|
||||
|
||||
// If file exists.
|
||||
_, err = os.Stat(statusFile)
|
||||
|
||||
if !os.IsNotExist(err) {
|
||||
b, err := os.ReadFile(statusFile)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Unable to read file %s: %s", statusFile, err)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
myStatus = strings.Trim(string(b), "\n")
|
||||
myStatus = strings.TrimSpace(string(b))
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
@@ -91,6 +95,7 @@ func (c *MyConfig) UpdateBatteryInfo() {
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Unable to convert string from file %s to integer", file)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -100,9 +105,13 @@ func (c *MyConfig) UpdateBatteryInfo() {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
batteries, _ = battery.GetAll()
|
||||
// In theory, this module should give for each entry its separate err, but in practice it gives
|
||||
// one single err for all entries, so we cannot detemine whist exatly entry errored.
|
||||
var err error
|
||||
|
||||
batteries, err = battery.GetAll()
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Unable to get battery info: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -250,3 +259,5 @@ func (c *MyConfig) UpdateBatteryInfo() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
|
||||
@@ -35,3 +35,5 @@ func (c *MyConfig) UpdateClock() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
// Collection is sync.Map, that stores arbitrary data.
|
||||
type Collection struct {
|
||||
items sync.Map
|
||||
close chan struct{}
|
||||
}
|
||||
|
||||
// Item just interface for stoing any data.
|
||||
@@ -17,9 +16,7 @@ type item struct {
|
||||
|
||||
// NewCollection creates new instance of "collection".
|
||||
func NewCollection() *Collection {
|
||||
c := &Collection{ //nolint:exhaustruct
|
||||
close: make(chan struct{}),
|
||||
}
|
||||
c := &Collection{}
|
||||
|
||||
return c
|
||||
}
|
||||
@@ -32,9 +29,12 @@ func (collection *Collection) Get(key any) (any, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
item := obj.(item)
|
||||
it, ok := obj.(item)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return item.data, true
|
||||
return it.data, true
|
||||
}
|
||||
|
||||
// Set saves value to given "collection".
|
||||
@@ -44,12 +44,15 @@ func (collection *Collection) Set(key any, value any) {
|
||||
})
|
||||
}
|
||||
|
||||
// Range apply function f to all keys/values in collection. Retuns immediatly on first error.
|
||||
// Range apply function f to all keys/values in collection. Returns immediately on first error.
|
||||
func (collection *Collection) Range(f func(key, value any) bool) {
|
||||
fn := func(key, value any) bool {
|
||||
item := value.(item)
|
||||
it, ok := value.(item)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
|
||||
return f(key, item.data)
|
||||
return f(key, it.data)
|
||||
}
|
||||
|
||||
collection.items.Range(fn)
|
||||
@@ -62,7 +65,6 @@ func (collection *Collection) Delete(key any) {
|
||||
|
||||
// Close frees memory occupied by collection and deletes collection itself.
|
||||
func (collection *Collection) Close() {
|
||||
collection.close <- struct{}{}
|
||||
collection.items = sync.Map{}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,19 +14,22 @@ import (
|
||||
p "github.com/mafik/pulseaudio"
|
||||
)
|
||||
|
||||
// I3BarOutBlock is structure element for I3BarOut, it represents i3bar output json block format.
|
||||
type I3BarOutBlock struct {
|
||||
type (
|
||||
// I3BarOutBlock is structure element for I3BarOut, it represents i3bar output json block format.
|
||||
I3BarOutBlock struct {
|
||||
FullText string `json:"full_text"`
|
||||
// ShortText will be shown if not enough room for FullText, threshold width defined in MinWidth
|
||||
// ShortText will be shown if not enough room for FullText, threshold width defined in MinWidth.
|
||||
ShortText string `json:"short_text,omitempty"`
|
||||
Color string `json:"color,omitempty"`
|
||||
Background string `json:"background,omitempty"`
|
||||
Font string `json:"font,omitempty"`
|
||||
FontSize string `json:"font_size,omitempty"`
|
||||
Border string `json:"border,omitempty"`
|
||||
BorderTop int `json:"border_top"`
|
||||
BorderRight int `json:"border_right"`
|
||||
BorderBottom int `json:"border_bottom"`
|
||||
BorderLeft int `json:"border_left"`
|
||||
// measured either in pixels or in characters, so either int or string, let's make it string :)
|
||||
// measured either in pixels or in characters, so either int or string, let's make it string :) .
|
||||
MinWidth string `json:"min_width,omitempty"`
|
||||
Align string `json:"align,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
@@ -35,29 +38,31 @@ type I3BarOutBlock struct {
|
||||
Separator bool `json:"separator"`
|
||||
SeparatorBlockWidth int `json:"separator_block_width"`
|
||||
Markup string `json:"markup,omitempty"`
|
||||
}
|
||||
}
|
||||
|
||||
type Separator struct {
|
||||
// Separator usually is a bymbol that separates fields in i3 status string.
|
||||
Separator struct {
|
||||
Left struct {
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Color string `json:"color,omitempty"`
|
||||
Background string `json:"background,omitempty"`
|
||||
Symbol string `json:"symbol,omitempty"`
|
||||
Font string `json:"font,omitempty"`
|
||||
FontSize string `json:"font_size,omitempty"`
|
||||
} `json:"left,omitempty"`
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
} `json:"left"`
|
||||
|
||||
Right struct {
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Color string `json:"color,omitempty"`
|
||||
Background string `json:"background,omitempty"`
|
||||
Symbol string `json:"symbol,omitempty"`
|
||||
Font string `json:"font,omitempty"`
|
||||
FontSize string `json:"font_size,omitempty"`
|
||||
} `json:"right,omitempty"`
|
||||
}
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
} `json:"right"`
|
||||
}
|
||||
|
||||
type MyConfig struct {
|
||||
// MyConfig internal represetation of running config state.
|
||||
MyConfig struct {
|
||||
Values struct {
|
||||
PrintOutput bool
|
||||
CPUTemperature int64
|
||||
@@ -69,6 +74,7 @@ type MyConfig struct {
|
||||
La string
|
||||
PA *p.Client
|
||||
SoundVolume string
|
||||
RunCommandOutput string
|
||||
}
|
||||
|
||||
Channels struct {
|
||||
@@ -79,21 +85,22 @@ type MyConfig struct {
|
||||
RunChan chan []string
|
||||
}
|
||||
|
||||
// Default text color
|
||||
// Color default text color.
|
||||
Color string `json:"color,omitempty"`
|
||||
|
||||
// Default background color
|
||||
// Background default background color.
|
||||
Background string `json:"background,omitempty"`
|
||||
|
||||
// Default text font
|
||||
// Font default text font.
|
||||
Font string `json:"font,omitempty"`
|
||||
|
||||
// Default text font size
|
||||
// FontSize default text font size.
|
||||
FontSize string `json:"font_size,omitempty"`
|
||||
|
||||
Separator Separator `json:"separator,omitempty"`
|
||||
// Separator i3status string separator configuration.
|
||||
Separator Separator `json:"separator"`
|
||||
|
||||
// LA Plugin
|
||||
// LA Plugin.
|
||||
LA struct {
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Color string `json:"color,omitempty"`
|
||||
@@ -101,9 +108,9 @@ type MyConfig struct {
|
||||
Font string `json:"font,omitempty"`
|
||||
FontSize string `json:"font_size,omitempty"`
|
||||
Separator Separator `json:"separator,omitempty"`
|
||||
} `json:"la,omitempty"`
|
||||
} `json:"la"`
|
||||
|
||||
// Mem plugin
|
||||
// Mem plugin.
|
||||
Mem struct {
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Color string `json:"color,omitempty"`
|
||||
@@ -112,8 +119,9 @@ type MyConfig struct {
|
||||
FontSize string `json:"font_size,omitempty"`
|
||||
ShowSwap bool `json:"show_swap,omitempty"`
|
||||
Separator Separator `json:"separator,omitempty"`
|
||||
} `json:"mem,omitempty"`
|
||||
} `json:"mem"`
|
||||
|
||||
// Clock plugin.
|
||||
Clock struct {
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Color string `json:"color,omitempty"`
|
||||
@@ -125,14 +133,15 @@ type MyConfig struct {
|
||||
LeftClick struct {
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Cmd []string `json:"cmd,omitempty"`
|
||||
} `json:"left_click,omitempty"`
|
||||
} `json:"left_click"`
|
||||
|
||||
RightClick struct {
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Cmd []string `json:"cmd,omitempty"`
|
||||
} `json:"right_click,omitempty"`
|
||||
} `json:"clock,omitempty"`
|
||||
} `json:"right_click"`
|
||||
} `json:"clock"`
|
||||
|
||||
// Battery plugin.
|
||||
Battery struct {
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
UseSysfs bool `json:"use_sysfs,omitempty"`
|
||||
@@ -150,11 +159,12 @@ type MyConfig struct {
|
||||
Empty string `json:"empty,omitempty"`
|
||||
AlmostFull string `json:"almost_full,omitempty"`
|
||||
AlmostEmpty string `json:"almost_empty,omitempty"`
|
||||
} `json:"charge_color,omitempty"`
|
||||
} `json:"charge_color"`
|
||||
|
||||
Separator Separator `json:"separator,omitempty"`
|
||||
} `json:"battery,omitempty"`
|
||||
} `json:"battery"`
|
||||
|
||||
// CPUTemp plugin.
|
||||
CPUTemp struct {
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Color string `json:"color,omitempty"`
|
||||
@@ -164,8 +174,9 @@ type MyConfig struct {
|
||||
Separator Separator `json:"separator,omitempty"`
|
||||
|
||||
File []string `json:"file,omitempty"`
|
||||
} `json:"cpu_temp,omitempty"`
|
||||
} `json:"cpu_temp"`
|
||||
|
||||
// Vpn plugin.
|
||||
Vpn struct {
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Color string `json:"color,omitempty"`
|
||||
@@ -176,16 +187,17 @@ type MyConfig struct {
|
||||
MtimeThreshold int `json:"mtime_threshold,omitempty"`
|
||||
DownColor string `json:"down_color,omitempty"`
|
||||
UpColor string `json:"up_color,omitempty"`
|
||||
Separator Separator `json:"separator,omitempty"`
|
||||
Separator Separator `json:"separator"`
|
||||
|
||||
TCPCheck struct {
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Host string `json:"host,omitempty"`
|
||||
Port int `json:"port,omitempty"`
|
||||
Timeout int `json:"timeout,omitempty"`
|
||||
} `json:"tcp_check,omitempty"`
|
||||
} `json:"vpn,omitempty"`
|
||||
} `json:"tcp_check"`
|
||||
} `json:"vpn"`
|
||||
|
||||
// SimpleVolumePa plugin.
|
||||
SimpleVolumePa struct {
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Color string `json:"color,omitempty"`
|
||||
@@ -203,8 +215,9 @@ type MyConfig struct {
|
||||
WheelUp int `json:"wheel_up,omitempty"`
|
||||
WheelDown int `json:"wheel_down,omitempty"`
|
||||
MaxVolumeLimit int `json:"max_volume_limit,omitempty"`
|
||||
} `json:"simple-volume-pa,omitempty"`
|
||||
} `json:"simple-volume-pa"`
|
||||
|
||||
// NrtIf plugin.
|
||||
NetIf struct {
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
DownColor string `json:"down_color,omitempty"`
|
||||
@@ -218,9 +231,10 @@ type MyConfig struct {
|
||||
If []struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Dir string `json:"dir,omitempty"`
|
||||
} `json:"if,omitempty"`
|
||||
} `json:"net-if,omitempty"`
|
||||
} `json:"if"`
|
||||
} `json:"net-if"`
|
||||
|
||||
// Cron plugin.
|
||||
Cron struct {
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
TimeZone string `json:"timezone,omitempty"`
|
||||
@@ -228,14 +242,33 @@ type MyConfig struct {
|
||||
Tasks []struct {
|
||||
Time string `json:"time,omitempty"`
|
||||
Cmd []string `json:"cmd,omitempty"`
|
||||
} `json:"tasks,omitempty"`
|
||||
} `json:"cron,omitempty"`
|
||||
} `json:"tasks"`
|
||||
} `json:"cron"`
|
||||
|
||||
// CmdRun plugin.
|
||||
CmdRun struct {
|
||||
Color string `json:"color,omitempty"`
|
||||
Background string `json:"background,omitempty"`
|
||||
Font string `json:"font,omitempty"`
|
||||
FontSize string `json:"font_size,omitempty"`
|
||||
Cmd string `json:"cmd,omitempty"`
|
||||
Args []string `json:"args,omitempty"`
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Delay int `json:"delay,omitempty"`
|
||||
Separator Separator `json:"separator,omitempty"`
|
||||
} `json:"cmdrun"`
|
||||
|
||||
// AppButtons plugin.
|
||||
AppButtons struct {
|
||||
Color string `json:"color,omitempty"`
|
||||
Background string `json:"background,omitempty"`
|
||||
Font string `json:"font,omitempty"`
|
||||
FontSize string `json:"font_size,omitempty"`
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Separator Separator `json:"separator,omitempty"`
|
||||
} `json:"app_buttons,omitempty"`
|
||||
} `json:"app_buttons"`
|
||||
|
||||
// Apps descriptions for AppButtons plugin.
|
||||
Apps []struct {
|
||||
FullText string `json:"full_text,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
@@ -245,14 +278,17 @@ type MyConfig struct {
|
||||
Class string `json:"class,omitempty"`
|
||||
Color string `json:"color,omitempty"`
|
||||
Background string `json:"background,omitempty"`
|
||||
Font string `json:"font,omitempty"`
|
||||
FontSize string `json:"font_size,omitempty"`
|
||||
Border string `json:"border,omitempty"`
|
||||
BorderActive string `json:"border_active,omitempty"`
|
||||
Separator bool `json:"separator,omitempty"`
|
||||
SeparatorBlockWidth int `json:"separator_block_width,omitempty"`
|
||||
} `json:"apps,omitempty"`
|
||||
}
|
||||
} `json:"apps"`
|
||||
}
|
||||
)
|
||||
|
||||
// readConf reads and validates config if config does not exist, it puts default config to the same dir where i3 config
|
||||
// ReadConf reads and validates config if config does not exist, it puts default config to the same dir where i3 config
|
||||
// is located.
|
||||
func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
||||
var (
|
||||
@@ -451,6 +487,30 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
||||
|
||||
if sampleConfig.LA.FontSize == "" {
|
||||
sampleConfig.LA.FontSize = sampleConfig.FontSize
|
||||
} else {
|
||||
matched, err := regexp.MatchString(
|
||||
`^(xx-small|x-small|small|medium|large|x-large|xx-large|smaller|larger)$`,
|
||||
sampleConfig.LA.FontSize,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.LA.FontSize: %s, fallback to %s",
|
||||
err,
|
||||
sampleConfig.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.LA.FontSize = sampleConfig.FontSize
|
||||
}
|
||||
|
||||
if !matched {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.LA.FontSize, fallback to %s",
|
||||
sampleConfig.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.LA.FontSize = sampleConfig.FontSize
|
||||
}
|
||||
}
|
||||
|
||||
if sampleConfig.LA.Separator.Left.Color == "" {
|
||||
@@ -505,22 +565,6 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
||||
sampleConfig.LA.Separator.Right.Background = sampleConfig.Separator.Right.Background
|
||||
}
|
||||
|
||||
if sampleConfig.LA.Separator.Right.Font == "" {
|
||||
sampleConfig.LA.Separator.Right.Font = sampleConfig.Separator.Right.Font
|
||||
}
|
||||
|
||||
if sampleConfig.LA.Separator.Right.FontSize == "" {
|
||||
sampleConfig.LA.Separator.Right.FontSize = sampleConfig.Separator.Right.FontSize
|
||||
}
|
||||
|
||||
if sampleConfig.LA.Separator.Right.Color == "" {
|
||||
sampleConfig.LA.Separator.Right.Color = sampleConfig.Separator.Right.Color
|
||||
}
|
||||
|
||||
if sampleConfig.LA.Separator.Right.Background == "" {
|
||||
sampleConfig.LA.Separator.Right.Background = sampleConfig.Separator.Right.Background
|
||||
}
|
||||
|
||||
if sampleConfig.LA.Separator.Right.Symbol == "" {
|
||||
sampleConfig.LA.Separator.Right.Symbol = sampleConfig.Separator.Right.Symbol
|
||||
}
|
||||
@@ -571,6 +615,30 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
||||
|
||||
if sampleConfig.Mem.FontSize == "" {
|
||||
sampleConfig.Mem.FontSize = sampleConfig.FontSize
|
||||
} else {
|
||||
matched, err := regexp.MatchString(
|
||||
`^(xx-small|x-small|small|medium|large|x-large|xx-large|smaller|larger)$`,
|
||||
sampleConfig.Mem.FontSize,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.Mem.FontSize: %s, fallback to %s",
|
||||
err,
|
||||
sampleConfig.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.Mem.FontSize = sampleConfig.FontSize
|
||||
}
|
||||
|
||||
if !matched {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.Mem.FontSize, fallback to %s",
|
||||
sampleConfig.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.Mem.FontSize = sampleConfig.FontSize
|
||||
}
|
||||
}
|
||||
|
||||
if sampleConfig.Mem.Separator.Left.Color == "" {
|
||||
@@ -675,6 +743,30 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
||||
|
||||
if sampleConfig.Clock.FontSize == "" {
|
||||
sampleConfig.Clock.FontSize = sampleConfig.FontSize
|
||||
} else {
|
||||
matched, err := regexp.MatchString(
|
||||
`^(xx-small|x-small|small|medium|large|x-large|xx-large|smaller|larger)$`,
|
||||
sampleConfig.Clock.FontSize,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.Clock.FontSize: %s, fallback to %s",
|
||||
err,
|
||||
sampleConfig.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.Clock.FontSize = sampleConfig.FontSize
|
||||
}
|
||||
|
||||
if !matched {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.Clock.FontSize, fallback to %s",
|
||||
sampleConfig.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.Clock.FontSize = sampleConfig.FontSize
|
||||
}
|
||||
}
|
||||
|
||||
if sampleConfig.Clock.Separator.Left.Enabled {
|
||||
@@ -767,20 +859,20 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// sampleConfig.Clock.LeftClick.Enabled will be false if not set in config
|
||||
// sampleConfig.Clock.LeftClick.Enabled will be false if not set in config.
|
||||
|
||||
if len(sampleConfig.Clock.LeftClick.Cmd) == 0 {
|
||||
sampleConfig.Clock.LeftClick.Cmd = append(sampleConfig.Clock.LeftClick.Cmd, "true")
|
||||
}
|
||||
|
||||
// sampleConfig.Clock.RightClick.Enabled will be false if not set in config
|
||||
// sampleConfig.Clock.RightClick.Enabled will be false if not set in config.
|
||||
|
||||
if len(sampleConfig.Clock.RightClick.Cmd) == 0 {
|
||||
sampleConfig.Clock.RightClick.Cmd = append(sampleConfig.Clock.RightClick.Cmd, "true")
|
||||
}
|
||||
|
||||
// sampleConfig.Battery.Enabled will be false if not set in config
|
||||
// sampleConfig.Battery.UseSysfs will be false if not set in config
|
||||
// sampleConfig.Battery.Enabled will be false if not set in config.
|
||||
// sampleConfig.Battery.UseSysfs will be false if not set in config.
|
||||
|
||||
if len(sampleConfig.Battery.SysfsFiles) == 0 {
|
||||
sampleConfig.Battery.SysfsFiles = append(
|
||||
@@ -803,6 +895,30 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
||||
|
||||
if sampleConfig.Battery.FontSize == "" {
|
||||
sampleConfig.Battery.FontSize = sampleConfig.FontSize
|
||||
} else {
|
||||
matched, err := regexp.MatchString(
|
||||
`^(xx-small|x-small|small|medium|large|x-large|xx-large|smaller|larger)$`,
|
||||
sampleConfig.Battery.FontSize,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.Battery.FontSize: %s, fallback to %s",
|
||||
err,
|
||||
sampleConfig.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.Battery.FontSize = sampleConfig.FontSize
|
||||
}
|
||||
|
||||
if !matched {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.Battery.FontSize, fallback to %s",
|
||||
sampleConfig.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.Battery.FontSize = sampleConfig.FontSize
|
||||
}
|
||||
}
|
||||
|
||||
if sampleConfig.Battery.Symbol == "" {
|
||||
@@ -814,13 +930,37 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
||||
}
|
||||
|
||||
if sampleConfig.Battery.SymbolFontSize == "" {
|
||||
sampleConfig.Battery.SymbolFontSize = sampleConfig.Battery.FontSize
|
||||
} else {
|
||||
matched, err := regexp.MatchString(
|
||||
`^(xx-small|x-small|small|medium|large|x-large|xx-large|smaller|larger)$`,
|
||||
sampleConfig.Battery.SymbolFontSize,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.Battery.SymbolFontSize: %s, fallback to %s",
|
||||
err,
|
||||
sampleConfig.Battery.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.Battery.SymbolFontSize = sampleConfig.Battery.FontSize
|
||||
}
|
||||
|
||||
// sampleConfig.Battery.ChargeColor.Full will be empty string if not set
|
||||
// sampleConfig.Battery.ChargeColor.Empty will be empty string if not set
|
||||
// sampleConfig.Battery.ChargeColor.AlmostFull will be empty string if not set
|
||||
// sampleConfig.Battery.ChargeColor.AlmostEmpty will be empty string if not set
|
||||
if !matched {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.Battery.SymbolFontSize, fallback to %s",
|
||||
sampleConfig.Battery.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.Battery.SymbolFontSize = sampleConfig.Battery.FontSize
|
||||
}
|
||||
}
|
||||
|
||||
// sampleConfig.Battery.ChargeColor.Full will be empty string if not set.
|
||||
// sampleConfig.Battery.ChargeColor.Empty will be empty string if not set.
|
||||
// sampleConfig.Battery.ChargeColor.AlmostFull will be empty string if not set.
|
||||
// sampleConfig.Battery.ChargeColor.AlmostEmpty will be empty string if not set.
|
||||
if sampleConfig.Battery.Separator.Left.Color == "" {
|
||||
sampleConfig.Battery.Separator.Left.Color = sampleConfig.Separator.Left.Color
|
||||
}
|
||||
@@ -909,9 +1049,9 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// sampleConfig.CpuTemp.Enabled will be false if not set in config
|
||||
// sampleConfig.CpuTemp.Enabled will be false if not set in config.
|
||||
|
||||
// No files configured - disable plugin
|
||||
// No files configured - disable plugin.
|
||||
if len(sampleConfig.CPUTemp.File) == 0 {
|
||||
sampleConfig.CPUTemp.Enabled = false
|
||||
}
|
||||
@@ -930,6 +1070,30 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
||||
|
||||
if sampleConfig.CPUTemp.FontSize == "" {
|
||||
sampleConfig.CPUTemp.FontSize = sampleConfig.FontSize
|
||||
} else {
|
||||
matched, err := regexp.MatchString(
|
||||
`^(xx-small|x-small|small|medium|large|x-large|xx-large|smaller|larger)$`,
|
||||
sampleConfig.CPUTemp.FontSize,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.CPUTemp.FontSize: %s, fallback to %s",
|
||||
err,
|
||||
sampleConfig.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.CPUTemp.FontSize = sampleConfig.FontSize
|
||||
}
|
||||
|
||||
if !matched {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.CPUTemp.FontSize, fallback to %s",
|
||||
sampleConfig.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.CPUTemp.FontSize = sampleConfig.FontSize
|
||||
}
|
||||
}
|
||||
|
||||
if sampleConfig.CPUTemp.Separator.Left.Enabled {
|
||||
@@ -1020,9 +1184,9 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// sampleConfig.Vpn.Enabled will false if not set in config
|
||||
// sampleConfig.Vpn.Enabled will false if not set in config.
|
||||
|
||||
// No status file - disable plugin
|
||||
// No status file - disable plugin.
|
||||
if sampleConfig.Vpn.StatusFile == "" {
|
||||
sampleConfig.Vpn.Enabled = false
|
||||
}
|
||||
@@ -1036,23 +1200,47 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
||||
}
|
||||
|
||||
if sampleConfig.Vpn.Font == "" {
|
||||
sampleConfig.Vpn.FontSize = sampleConfig.Font
|
||||
sampleConfig.Vpn.Font = sampleConfig.Font
|
||||
}
|
||||
|
||||
if sampleConfig.Vpn.FontSize == "" {
|
||||
sampleConfig.Vpn.FontSize = sampleConfig.FontSize
|
||||
} else {
|
||||
matched, err := regexp.MatchString(
|
||||
`^(xx-small|x-small|small|medium|large|x-large|xx-large|smaller|larger)$`,
|
||||
sampleConfig.Vpn.FontSize,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.Vpn.FontSize: %s, fallback to %s",
|
||||
err,
|
||||
sampleConfig.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.Vpn.FontSize = sampleConfig.FontSize
|
||||
}
|
||||
|
||||
// Check status file at least once per 3 seconds
|
||||
if !matched {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.Vpn.FontSize, fallback to %s",
|
||||
sampleConfig.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.Vpn.FontSize = sampleConfig.FontSize
|
||||
}
|
||||
}
|
||||
|
||||
// Check status file at least once per 3 seconds.
|
||||
if sampleConfig.Vpn.MtimeThreshold < 3 {
|
||||
log.Printf("vpn.mtime_threshold not set, using 3")
|
||||
|
||||
sampleConfig.Vpn.MtimeThreshold = 3
|
||||
}
|
||||
|
||||
// sampleConfig.Vpn.DownColor will be empty string if no value set in config
|
||||
// sampleConfig.Vpn.UpColor will be empty string if no value set in config
|
||||
// sampleConfig.Vpn.TcpCheck.Enabled will false if not set in config
|
||||
// sampleConfig.Vpn.DownColor will be empty string if no value set in config.
|
||||
// sampleConfig.Vpn.UpColor will be empty string if no value set in config.
|
||||
// sampleConfig.Vpn.TcpCheck.Enabled will false if not set in config.
|
||||
|
||||
if sampleConfig.Vpn.Separator.Left.Enabled {
|
||||
if sampleConfig.Vpn.Separator.Left.Color == "" {
|
||||
@@ -1144,7 +1332,7 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Disable plugin if value inadequate
|
||||
// Disable plugin if value inadequate.
|
||||
if sampleConfig.Vpn.TCPCheck.Port > 65535 {
|
||||
if sampleConfig.Vpn.TCPCheck.Enabled {
|
||||
log.Printf("vpn.tcp_check.port > 65535, disabling vpn.tcp_check.enabled")
|
||||
@@ -1153,7 +1341,7 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
||||
sampleConfig.Vpn.TCPCheck.Enabled = false
|
||||
}
|
||||
|
||||
// Disable plugin if value indaquate
|
||||
// Disable plugin if value indaquate.
|
||||
if sampleConfig.Vpn.TCPCheck.Host == "" {
|
||||
if sampleConfig.Vpn.TCPCheck.Enabled {
|
||||
log.Printf("vpn.tcp_check.host not set, disabling vpn.tcp_check.enabled")
|
||||
@@ -1170,7 +1358,7 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
||||
sampleConfig.Vpn.TCPCheck.Timeout = 3
|
||||
}
|
||||
|
||||
// sampleConfig.SimpleVolumePa.Enabled will false if not set in config
|
||||
// sampleConfig.SimpleVolumePa.Enabled will false if not set in config.
|
||||
if sampleConfig.SimpleVolumePa.Color == "" {
|
||||
sampleConfig.SimpleVolumePa.Color = sampleConfig.Color
|
||||
}
|
||||
@@ -1185,6 +1373,30 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
||||
|
||||
if sampleConfig.SimpleVolumePa.FontSize == "" {
|
||||
sampleConfig.SimpleVolumePa.FontSize = sampleConfig.FontSize
|
||||
} else {
|
||||
matched, err := regexp.MatchString(
|
||||
`^(xx-small|x-small|small|medium|large|x-large|xx-large|smaller|larger)$`,
|
||||
sampleConfig.SimpleVolumePa.FontSize,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.SimpleVolumePa.FontSize: %s, fallback to %s",
|
||||
err,
|
||||
sampleConfig.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.SimpleVolumePa.FontSize = sampleConfig.FontSize
|
||||
}
|
||||
|
||||
if !matched {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.SimpleVolumePa.FontSize, fallback to %s",
|
||||
sampleConfig.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.SimpleVolumePa.FontSize = sampleConfig.FontSize
|
||||
}
|
||||
}
|
||||
|
||||
if sampleConfig.SimpleVolumePa.Symbol == "" {
|
||||
@@ -1197,6 +1409,30 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
||||
|
||||
if sampleConfig.SimpleVolumePa.SymbolFontSize == "" {
|
||||
sampleConfig.SimpleVolumePa.SymbolFontSize = sampleConfig.SimpleVolumePa.FontSize
|
||||
} else {
|
||||
matched, err := regexp.MatchString(
|
||||
`^(xx-small|x-small|small|medium|large|x-large|xx-large|smaller|larger)$`,
|
||||
sampleConfig.SimpleVolumePa.SymbolFontSize,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.SimpleVolumePa.SymbolFontSize: %s, fallback to %s",
|
||||
err,
|
||||
sampleConfig.SimpleVolumePa.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.SimpleVolumePa.SymbolFontSize = sampleConfig.SimpleVolumePa.FontSize
|
||||
}
|
||||
|
||||
if !matched {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.SimpleVolumePa.SymbolFontSize, fallback to %s",
|
||||
sampleConfig.SimpleVolumePa.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.SimpleVolumePa.SymbolFontSize = sampleConfig.SimpleVolumePa.FontSize
|
||||
}
|
||||
}
|
||||
|
||||
if sampleConfig.SimpleVolumePa.Step == 0 {
|
||||
@@ -1319,7 +1555,7 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// sampleConfig.Cron.Enabled will false if not set in config
|
||||
// sampleConfig.Cron.Enabled will false if not set in config.
|
||||
|
||||
if len(sampleConfig.Cron.Tasks) == 0 {
|
||||
sampleConfig.Cron.Enabled = false
|
||||
@@ -1329,7 +1565,7 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
||||
sampleConfig.Cron.TimeZone = "GMT+0"
|
||||
}
|
||||
|
||||
// sampleConfig.NetIf.Enabled will false if not set in config
|
||||
// sampleConfig.NetIf.Enabled will false if not set in config.
|
||||
|
||||
if len(sampleConfig.NetIf.If) == 0 {
|
||||
sampleConfig.NetIf.Enabled = false
|
||||
@@ -1357,6 +1593,29 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
||||
|
||||
if sampleConfig.NetIf.FontSize == "" {
|
||||
sampleConfig.NetIf.FontSize = sampleConfig.FontSize
|
||||
} else {
|
||||
matched, err := regexp.MatchString(
|
||||
`^(xx-small|x-small|small|medium|large|x-large|xx-large|smaller|larger)$`,
|
||||
sampleConfig.NetIf.FontSize,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.NetIf.FontSize: %s, fallback to %s",
|
||||
err,
|
||||
sampleConfig.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.NetIf.FontSize = sampleConfig.FontSize
|
||||
}
|
||||
|
||||
if !matched {
|
||||
log.Printf("Unable to set sampleConfig.NetIf.FontSize, fallback to %s",
|
||||
sampleConfig.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.NetIf.FontSize = sampleConfig.FontSize
|
||||
}
|
||||
}
|
||||
|
||||
if sampleConfig.NetIf.Separator.Left.Color == "" {
|
||||
@@ -1446,7 +1705,186 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// sampleConfig.AppButtons.Enabled will false if not set in config
|
||||
// sampleConfig.CmdRun.Enabled will false if not set in config.
|
||||
|
||||
if sampleConfig.CmdRun.Cmd == "" && sampleConfig.CmdRun.Enabled {
|
||||
sampleConfig.CmdRun.Enabled = false
|
||||
|
||||
log.Print(
|
||||
"Setting sampleConfig.CmdRun.Enabled to false because sampleConfig.CmdRun.Cmd is not set",
|
||||
)
|
||||
}
|
||||
|
||||
// sampleConfig.CmdRun.Args can be empty.
|
||||
|
||||
if sampleConfig.CmdRun.Color == "" {
|
||||
sampleConfig.CmdRun.Color = sampleConfig.Color
|
||||
}
|
||||
|
||||
if sampleConfig.CmdRun.Background == "" {
|
||||
sampleConfig.CmdRun.Background = sampleConfig.Background
|
||||
}
|
||||
|
||||
if sampleConfig.CmdRun.Font == "" {
|
||||
sampleConfig.CmdRun.Font = sampleConfig.Font
|
||||
}
|
||||
|
||||
if sampleConfig.CmdRun.FontSize == "" {
|
||||
sampleConfig.CmdRun.FontSize = sampleConfig.FontSize
|
||||
} else {
|
||||
matched, err := regexp.MatchString(
|
||||
`^(xx-small|x-small|small|medium|large|x-large|xx-large|smaller|larger)$`,
|
||||
sampleConfig.CmdRun.FontSize,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.CmdRun.FontSize: %s, fallback to %s",
|
||||
err,
|
||||
sampleConfig.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.CmdRun.FontSize = sampleConfig.FontSize
|
||||
}
|
||||
|
||||
if !matched {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.CmdRun.FontSize, fallback to %s",
|
||||
sampleConfig.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.CmdRun.FontSize = sampleConfig.FontSize
|
||||
}
|
||||
}
|
||||
|
||||
if sampleConfig.CmdRun.Separator.Left.Color == "" {
|
||||
sampleConfig.CmdRun.Separator.Left.Color = sampleConfig.Separator.Left.Color
|
||||
}
|
||||
|
||||
if sampleConfig.CmdRun.Separator.Left.Background == "" {
|
||||
sampleConfig.CmdRun.Separator.Left.Background = sampleConfig.Separator.Left.Background
|
||||
}
|
||||
|
||||
if sampleConfig.CmdRun.Separator.Left.Symbol == "" {
|
||||
sampleConfig.CmdRun.Separator.Left.Symbol = sampleConfig.Separator.Left.Symbol
|
||||
}
|
||||
|
||||
if sampleConfig.CmdRun.Separator.Left.Font == "" {
|
||||
sampleConfig.CmdRun.Separator.Left.Font = sampleConfig.Separator.Left.Font
|
||||
}
|
||||
|
||||
if sampleConfig.CmdRun.Separator.Left.FontSize == "" {
|
||||
sampleConfig.CmdRun.Separator.Left.FontSize = sampleConfig.Separator.Left.FontSize
|
||||
} else {
|
||||
matched, err := regexp.MatchString(
|
||||
`^(xx-small|x-small|small|medium|large|x-large|xx-large|smaller|larger)$`,
|
||||
sampleConfig.CmdRun.Separator.Left.FontSize,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.CmdRun.Separator.Left.FontSize: %s, fallback to %s",
|
||||
err,
|
||||
sampleConfig.Separator.Left.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.CmdRun.Separator.Left.FontSize = sampleConfig.Separator.Left.FontSize
|
||||
}
|
||||
|
||||
if !matched {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.CmdRun.Separator.Left.FontSize, fallback to %s",
|
||||
sampleConfig.Separator.Left.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.CmdRun.Separator.Left.FontSize = sampleConfig.Separator.Left.FontSize
|
||||
}
|
||||
}
|
||||
|
||||
if sampleConfig.CmdRun.Separator.Right.Color == "" {
|
||||
sampleConfig.CmdRun.Separator.Right.Color = sampleConfig.Separator.Right.Color
|
||||
}
|
||||
|
||||
if sampleConfig.CmdRun.Separator.Right.Background == "" {
|
||||
sampleConfig.CmdRun.Separator.Right.Background = sampleConfig.Separator.Right.Background
|
||||
}
|
||||
|
||||
if sampleConfig.CmdRun.Separator.Right.Symbol == "" {
|
||||
sampleConfig.CmdRun.Separator.Right.Symbol = sampleConfig.Separator.Right.Symbol
|
||||
}
|
||||
|
||||
if sampleConfig.CmdRun.Separator.Right.Font == "" {
|
||||
sampleConfig.CmdRun.Separator.Right.Font = sampleConfig.Separator.Right.Font
|
||||
}
|
||||
|
||||
if sampleConfig.CmdRun.Separator.Right.FontSize == "" {
|
||||
sampleConfig.CmdRun.Separator.Right.FontSize = sampleConfig.Separator.Right.FontSize
|
||||
} else {
|
||||
matched, err := regexp.MatchString(
|
||||
`^(xx-small|x-small|small|medium|large|x-large|xx-large|smaller|larger)$`,
|
||||
sampleConfig.CmdRun.Separator.Right.FontSize,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.CmdRun.Separator.Right.FontSize: %s, fallback to %s",
|
||||
err,
|
||||
sampleConfig.Separator.Right.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.CmdRun.Separator.Right.FontSize = sampleConfig.Separator.Right.FontSize
|
||||
}
|
||||
|
||||
if !matched {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.CmdRun.Separator.Right.FontSize, fallback to %s",
|
||||
sampleConfig.Separator.Right.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.CmdRun.Separator.Right.FontSize = sampleConfig.Separator.Right.FontSize
|
||||
}
|
||||
}
|
||||
|
||||
// sampleConfig.AppButtons.Enabled will false if not set in config.
|
||||
if sampleConfig.AppButtons.Color == "" {
|
||||
sampleConfig.AppButtons.Color = sampleConfig.Color
|
||||
}
|
||||
|
||||
if sampleConfig.AppButtons.Background == "" {
|
||||
sampleConfig.AppButtons.Background = sampleConfig.Background
|
||||
}
|
||||
|
||||
if sampleConfig.AppButtons.Font == "" {
|
||||
sampleConfig.AppButtons.Font = sampleConfig.Font
|
||||
}
|
||||
|
||||
if sampleConfig.AppButtons.FontSize == "" {
|
||||
sampleConfig.AppButtons.FontSize = sampleConfig.FontSize
|
||||
} else {
|
||||
matched, err := regexp.MatchString(
|
||||
`^(xx-small|x-small|small|medium|large|x-large|xx-large|smaller|larger)$`,
|
||||
sampleConfig.AppButtons.FontSize,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.AppButtons.FontSize: %s, fallback to %s",
|
||||
err,
|
||||
sampleConfig.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.AppButtons.FontSize = sampleConfig.FontSize
|
||||
}
|
||||
|
||||
if !matched {
|
||||
log.Printf(
|
||||
"Unable to set sampleConfig.AppButtons.FontSize, fallback to %s",
|
||||
sampleConfig.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.AppButtons.FontSize = sampleConfig.FontSize
|
||||
}
|
||||
}
|
||||
|
||||
if sampleConfig.AppButtons.Separator.Left.Color == "" {
|
||||
sampleConfig.AppButtons.Separator.Left.Color = sampleConfig.Separator.Left.Color
|
||||
@@ -1542,34 +1980,68 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
||||
// app.Instance can be missing.
|
||||
// app.Class can be missing.
|
||||
if app.Name == "" {
|
||||
app.Name = fmt.Sprintf("app%d", num)
|
||||
sampleConfig.Apps[num].Name = fmt.Sprintf("app%d", num)
|
||||
}
|
||||
|
||||
// app.Args can be empty slice. In that case command will be run without aruments.
|
||||
if app.Cmd == "" {
|
||||
app.Cmd = "true"
|
||||
// If command omitted it will be just /usr/bin/true.
|
||||
sampleConfig.Apps[num].Cmd = "true"
|
||||
}
|
||||
|
||||
if app.Color == "" {
|
||||
app.Color = sampleConfig.Color
|
||||
sampleConfig.Apps[num].Color = sampleConfig.AppButtons.Color
|
||||
}
|
||||
|
||||
if app.Background == "" {
|
||||
app.Background = sampleConfig.Background
|
||||
sampleConfig.Apps[num].Background = sampleConfig.AppButtons.Background
|
||||
}
|
||||
|
||||
if app.Font == "" {
|
||||
sampleConfig.Apps[num].Font = sampleConfig.AppButtons.Font
|
||||
}
|
||||
|
||||
if app.FontSize == "" {
|
||||
sampleConfig.Apps[num].FontSize = sampleConfig.AppButtons.FontSize
|
||||
} else {
|
||||
matched, err := regexp.MatchString(
|
||||
`^(xx-small|x-small|small|medium|large|x-large|xx-large|smaller|larger)$`,
|
||||
app.FontSize,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Printf(
|
||||
"Unable to set %s.FontSize: %s, fallback to %s",
|
||||
app.Name,
|
||||
err,
|
||||
sampleConfig.AppButtons.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.Apps[num].FontSize = sampleConfig.AppButtons.FontSize
|
||||
}
|
||||
|
||||
if !matched {
|
||||
log.Printf("Unable to set %s.FontSize, fallback to %s",
|
||||
app.Name,
|
||||
sampleConfig.AppButtons.FontSize,
|
||||
)
|
||||
|
||||
sampleConfig.Apps[num].FontSize = sampleConfig.AppButtons.FontSize
|
||||
}
|
||||
}
|
||||
|
||||
if app.Border == "" {
|
||||
app.Border = sampleConfig.Color
|
||||
sampleConfig.Apps[num].Border = sampleConfig.AppButtons.Color
|
||||
}
|
||||
|
||||
if app.BorderActive == "" {
|
||||
app.BorderActive = sampleConfig.Color
|
||||
sampleConfig.Apps[num].BorderActive = sampleConfig.AppButtons.Color
|
||||
}
|
||||
|
||||
// app.Separator can be omitted, in that case it is false
|
||||
// app.SeparatorBlockWidth can be missing
|
||||
// app.Separator can be omitted, in that case it is false.
|
||||
// app.SeparatorBlockWidth can be missing.
|
||||
if app.FullText == "" {
|
||||
app.FullText = fmt.Sprintf(" %d ", num)
|
||||
sampleConfig.Apps[num].FullText = fmt.Sprintf(" %d ", num)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1591,3 +2063,5 @@ func LocateConfFile() (string, error) {
|
||||
|
||||
return filepath.Dir(i3ConfigPath) + "/i3status-go.json", nil
|
||||
}
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
|
||||
@@ -23,6 +23,7 @@ func (c *MyConfig) UpdateCPUTemperature() {
|
||||
temperature = make([]int64, n)
|
||||
tSum int64
|
||||
tAvg int64
|
||||
validCount int
|
||||
)
|
||||
|
||||
if Delay == InitialDelay {
|
||||
@@ -35,47 +36,50 @@ func (c *MyConfig) UpdateCPUTemperature() {
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Unable to open %s: %s", filename, err)
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
reader := bufio.NewReader(file)
|
||||
line, _, err := reader.ReadLine()
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Unable to read from %s: %s", filename, err)
|
||||
err = file.Close()
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Unable to close %s: %s", filename, err)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
err = file.Close()
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Unable to close %s: %s", filename, err)
|
||||
} else {
|
||||
temp, err := strconv.ParseInt(string(line), 10, 32)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Unable to convert string to number from file %s: %s", filename, err)
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
|
||||
if temp > 1000 {
|
||||
temp /= 1000
|
||||
}
|
||||
|
||||
temperature[i] = temp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
validCount++
|
||||
}
|
||||
|
||||
if len(temperature) == 1 {
|
||||
tAvg = temperature[0]
|
||||
if validCount == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if validCount == 1 {
|
||||
for _, t := range temperature {
|
||||
if t != 0 {
|
||||
tAvg = t
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, t := range temperature {
|
||||
tSum += t
|
||||
}
|
||||
|
||||
tAvg = tSum / int64(len(temperature))
|
||||
tAvg = tSum / int64(validCount)
|
||||
}
|
||||
|
||||
if c.Values.CPUTemperature != tAvg {
|
||||
@@ -84,3 +88,5 @@ func (c *MyConfig) UpdateCPUTemperature() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
|
||||
@@ -7,7 +7,9 @@ import (
|
||||
)
|
||||
|
||||
// myCron contains cron handler.
|
||||
var myCron gocron.Scheduler
|
||||
var (
|
||||
myCron gocron.Scheduler
|
||||
)
|
||||
|
||||
// RunCron parses config part, related to cron tasks and kicks cron to run.
|
||||
func (c MyConfig) RunCron() {
|
||||
@@ -25,15 +27,12 @@ func (c MyConfig) RunCron() {
|
||||
_, err := myCron.NewJob(
|
||||
gocron.CronJob(job.Time, false),
|
||||
gocron.NewTask(
|
||||
// Сука, просто заспавнить бинарь, ну почему это надо делать через жопу-то?
|
||||
any(
|
||||
func() bool {
|
||||
c.Channels.RunChan <- job.Cmd
|
||||
|
||||
return true
|
||||
},
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
@@ -43,3 +42,5 @@ func (c MyConfig) RunCron() {
|
||||
|
||||
myCron.Start()
|
||||
}
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
|
||||
@@ -19,15 +19,18 @@ var WL WinList
|
||||
|
||||
// UpdateI3WinList subsribes to all window-related events and send them to I3EventParser() for more detailed parsing.
|
||||
func (c *MyConfig) UpdateI3WinList() {
|
||||
// TODO: Здесь получить начальный список окон, управляемых i3wm (через GetTree()) и сложить их атрибутику в переменную WL
|
||||
Tree, err := i3.GetTree()
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Unable to get list of windows: %s", err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
c.ExtractProps(Tree.Root)
|
||||
|
||||
c.Channels.UpdateReady <- true
|
||||
|
||||
i3wm := i3.Subscribe(i3.WindowEventType)
|
||||
|
||||
for i3wm.Next() {
|
||||
@@ -105,9 +108,11 @@ func (c *MyConfig) I3EventParser(e *i3.WindowEvent) {
|
||||
|
||||
// interfaceToUint превращает данный интерфейс в Uint64.
|
||||
// Если может, конечно :) .
|
||||
func interfaceToUint64(iface interface{}) uint64 {
|
||||
// А теперь мы начинаем дурдом, нам надо превратить ёбанный interface{} в []string
|
||||
// Поскольку interface{} может быть чем угодно, перестрахуемся
|
||||
func interfaceToUint64(iface any) uint64 {
|
||||
if iface == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
if reflect.TypeOf(iface).Kind() == reflect.Uint64 {
|
||||
return reflect.ValueOf(iface).Uint()
|
||||
}
|
||||
@@ -152,18 +157,16 @@ func HasWindows(className string, instanceName string) bool {
|
||||
func FindWindowInstance(regexpStr string) bool {
|
||||
var found = false
|
||||
|
||||
f := func(key any, value any) bool { //nolint: revive
|
||||
keyStr := reflect.ValueOf(key).String()
|
||||
|
||||
re, err := regexp.Compile(regexpStr) // we do not want shit our pants and panic on
|
||||
// erroneous regexp, we want log it to stderr, that it.
|
||||
|
||||
re, err := regexp.Compile(regexpStr)
|
||||
if err != nil {
|
||||
log.Printf("Unable to perform regexp match: %s", err)
|
||||
|
||||
return true
|
||||
return false
|
||||
}
|
||||
|
||||
f := func(key any, value any) bool { //nolint: revive
|
||||
keyStr := reflect.ValueOf(key).String()
|
||||
|
||||
if re.Match([]byte(keyStr)) { //nolint:mirror
|
||||
found = true
|
||||
|
||||
@@ -183,18 +186,16 @@ func FindWindowInstance(regexpStr string) bool {
|
||||
func FindWindowClass(regexpStr string) bool {
|
||||
var found = false
|
||||
|
||||
f := func(key any, value any) bool { //nolint: revive
|
||||
keyStr := reflect.ValueOf(key).String()
|
||||
|
||||
re, err := regexp.Compile(regexpStr) // we do not want shit our pants and panic on
|
||||
// erroneous regexp, we want log it to stderr, that it.
|
||||
|
||||
re, err := regexp.Compile(regexpStr)
|
||||
if err != nil {
|
||||
log.Printf("Unable to perform regexp match: %s", err)
|
||||
|
||||
return true
|
||||
return false
|
||||
}
|
||||
|
||||
f := func(key any, value any) bool { //nolint: revive
|
||||
keyStr := reflect.ValueOf(key).String()
|
||||
|
||||
if re.Match([]byte(keyStr)) { //nolint:mirror
|
||||
found = true
|
||||
|
||||
@@ -225,3 +226,5 @@ func (c *MyConfig) ExtractProps(n *i3.Node) {
|
||||
c.ExtractProps(node)
|
||||
}
|
||||
}
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
|
||||
@@ -44,8 +44,8 @@ func (c *MyConfig) UpdateIfStatus() {
|
||||
} else {
|
||||
switch strings.TrimSpace(string(operstate)) {
|
||||
case "up":
|
||||
StatusStr := fmt.Sprintf("<span foreground=\"%s\">⍋</span>", c.NetIf.UpColor)
|
||||
operstate = []byte(StatusStr)
|
||||
statusStr := fmt.Sprintf("<span foreground=\"%s\">⍋</span>", c.NetIf.UpColor)
|
||||
operstate = []byte(statusStr)
|
||||
case "down":
|
||||
statusStr := fmt.Sprintf("<span foreground=\"%s\">⍒</span>", c.NetIf.DownColor)
|
||||
operstate = []byte(statusStr)
|
||||
@@ -67,3 +67,5 @@ func (c *MyConfig) UpdateIfStatus() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
|
||||
@@ -2,6 +2,7 @@ package lib
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/shirou/gopsutil/load"
|
||||
@@ -22,7 +23,13 @@ func (c *MyConfig) UpdateLaStats() {
|
||||
ticker.Reset(Delay)
|
||||
}
|
||||
|
||||
l, _ := load.Avg()
|
||||
l, err := load.Avg()
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Unable to get LA stats: %s", err)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
lav := fmt.Sprintf("%.2f", l.Load1)
|
||||
|
||||
@@ -32,3 +39,5 @@ func (c *MyConfig) UpdateLaStats() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
|
||||
@@ -38,6 +38,7 @@ func (c *MyConfig) UpdateMemStats() {
|
||||
continue
|
||||
}
|
||||
|
||||
if c.Mem.ShowSwap {
|
||||
sw, err := mem.SwapMemory()
|
||||
|
||||
if err != nil {
|
||||
@@ -47,11 +48,10 @@ func (c *MyConfig) UpdateMemStats() {
|
||||
continue
|
||||
}
|
||||
|
||||
if c.Mem.ShowSwap {
|
||||
if c.Values.Memory.Usedpct != uint64(v.UsedPercent) || c.Values.Memory.Shared != v.Shared/1024/1024 || c.Values.Memory.Swap != v.SwapTotal-v.SwapFree {
|
||||
if c.Values.Memory.Usedpct != uint64(v.UsedPercent) || c.Values.Memory.Shared != v.Shared/1024/1024 || c.Values.Memory.Swap != sw.Used/1024/1024 {
|
||||
c.Values.Memory.Usedpct = uint64(v.UsedPercent)
|
||||
c.Values.Memory.Shared = v.Shared / 1024 / 1024
|
||||
c.Values.Memory.Swap = sw.Used
|
||||
c.Values.Memory.Swap = sw.Used / 1024 / 1024
|
||||
c.Channels.UpdateReady <- true
|
||||
}
|
||||
} else {
|
||||
@@ -63,3 +63,5 @@ func (c *MyConfig) UpdateMemStats() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
|
||||
@@ -113,12 +113,12 @@ func (c *MyConfig) PaReinit() error {
|
||||
var err error
|
||||
|
||||
// If we out of updates, seems someone killed pulseaudio server. Restart it.
|
||||
cmd := exec.Command("pulseaudio", "--check")
|
||||
cmd := exec.Command("pulseaudio", "--check") //nolint: noctx
|
||||
|
||||
if err := cmd.Run(); err == nil {
|
||||
log.Printf("pulseaudio already running, but seems not responding, try gracefully kill it")
|
||||
|
||||
cmd = exec.Command("pulseaudio", "--kill")
|
||||
cmd = exec.Command("pulseaudio", "--kill") //nolint: noctx
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("unable to kill pulseaudio: %w", err)
|
||||
@@ -127,7 +127,7 @@ func (c *MyConfig) PaReinit() error {
|
||||
cnt := 0
|
||||
|
||||
for {
|
||||
cmd := exec.Command("pulseaudio", "--check")
|
||||
cmd := exec.Command("pulseaudio", "--check") //nolint: noctx
|
||||
|
||||
// PA not running. Breakout of loop.
|
||||
if err := cmd.Run(); err != nil {
|
||||
@@ -154,10 +154,10 @@ func (c *MyConfig) PaReinit() error {
|
||||
// audio.
|
||||
if c.SimpleVolumePa.DontExitOnLogin {
|
||||
// Do not exit on any kind of login/logout events.
|
||||
cmd = exec.Command("pulseaudio", "--exit-idle-time=-1", "--start")
|
||||
cmd = exec.Command("pulseaudio", "--exit-idle-time=-1", "--start") //nolint: noctx
|
||||
} else {
|
||||
// Exit immediately on logout(?).
|
||||
cmd = exec.Command("pulseaudio", "--exit-idle-time=0", "--start")
|
||||
cmd = exec.Command("pulseaudio", "--exit-idle-time=0", "--start") //nolint: noctx
|
||||
}
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
@@ -173,6 +173,8 @@ func (c *MyConfig) PaReinit() error {
|
||||
return err
|
||||
}
|
||||
|
||||
// SVPAHandler simple volume pulse audio handler works with events sent to SVPAHandlerChan cahnnel. Left/right clicks,
|
||||
// wheel turning events etc.
|
||||
func (c *MyConfig) SVPAHandler() {
|
||||
for e := range c.Channels.SVPAHandlerChan {
|
||||
if e.Button == 3 {
|
||||
@@ -220,3 +222,5 @@ func (c *MyConfig) SVPAHandler() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
|
||||
43
internal/lib/runcommand.go
Normal file
43
internal/lib/runcommand.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
// RunCommand gets list of commands runs them sequentally and conacatenates their output.
|
||||
func (c *MyConfig) RunCommand() {
|
||||
var (
|
||||
InitialDelay = 100 * time.Millisecond
|
||||
LoopIterationDelay = time.Duration(c.CmdRun.Delay) * time.Second
|
||||
Delay = InitialDelay
|
||||
ticker = time.NewTicker(Delay)
|
||||
)
|
||||
|
||||
for range ticker.C {
|
||||
if Delay == InitialDelay {
|
||||
Delay = LoopIterationDelay
|
||||
ticker.Reset(Delay)
|
||||
}
|
||||
|
||||
var (
|
||||
outputString string
|
||||
command = []string{c.CmdRun.Cmd}
|
||||
)
|
||||
|
||||
if len(c.CmdRun.Args) > 0 {
|
||||
command = append(command, c.CmdRun.Args...)
|
||||
}
|
||||
|
||||
outputString += RunProcess(command)
|
||||
|
||||
log.Println(outputString)
|
||||
|
||||
if c.Values.RunCommandOutput != outputString {
|
||||
c.Values.RunCommandOutput = outputString
|
||||
c.Channels.UpdateReady <- true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
@@ -6,8 +6,6 @@ import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var PrintOutput = true
|
||||
|
||||
// SigHandler OS signal handler.
|
||||
func (c *MyConfig) SigHandler() {
|
||||
for s := range c.Channels.SigChan {
|
||||
@@ -33,3 +31,5 @@ func (c *MyConfig) SigHandler() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
@@ -11,9 +13,21 @@ import (
|
||||
// Spawner forks and execs given program, and also detaches form its control tty.
|
||||
func (c *MyConfig) Spawner() {
|
||||
for prg := range c.Channels.RunChan {
|
||||
<-time.After(25 * time.Millisecond)
|
||||
devnullR, _ := os.Open(os.DevNull)
|
||||
devnullW, _ := os.OpenFile(os.DevNull, os.O_WRONLY|os.O_APPEND, 0644)
|
||||
time.Sleep(25 * time.Millisecond)
|
||||
|
||||
devnullR, err := os.Open(os.DevNull)
|
||||
if err != nil {
|
||||
log.Printf("Unable to open /dev/null for reading: %s", err)
|
||||
continue
|
||||
}
|
||||
defer devnullR.Close()
|
||||
|
||||
devnullW, err := os.OpenFile(os.DevNull, os.O_WRONLY|os.O_APPEND, 0644)
|
||||
if err != nil {
|
||||
log.Printf("Unable to open /dev/null for writing: %s", err)
|
||||
continue
|
||||
}
|
||||
defer devnullW.Close()
|
||||
|
||||
spa := syscall.SysProcAttr{
|
||||
Setsid: true,
|
||||
@@ -31,6 +45,7 @@ func (c *MyConfig) Spawner() {
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Unable to spawn %s: %s", prg[0], err)
|
||||
continue
|
||||
}
|
||||
|
||||
_, err = syscall.ForkExec(bin, prg, &pa)
|
||||
@@ -38,10 +53,6 @@ func (c *MyConfig) Spawner() {
|
||||
if err != nil {
|
||||
log.Printf("Unable to spawn %s: %s", prg[0], err)
|
||||
}
|
||||
|
||||
// Close file errors we don't handle :) at all.
|
||||
_ = devnullR.Close()
|
||||
_ = devnullW.Close()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,8 +61,52 @@ func (c *MyConfig) CleanZombies() {
|
||||
r := syscall.Rusage{}
|
||||
|
||||
for {
|
||||
_, _ = syscall.Wait4(-1, nil, 0, &r)
|
||||
pid, _ := syscall.Wait4(-1, nil, syscall.WNOHANG, &r)
|
||||
|
||||
if pid > 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
time.Sleep(1 * time.Minute)
|
||||
}
|
||||
}
|
||||
|
||||
// RunProcess runs given command and returns contents of command stdout. On error prints error on stderr and returns
|
||||
// empty syting.
|
||||
func RunProcess(command []string) string {
|
||||
var (
|
||||
cmd *exec.Cmd
|
||||
stdout, stderr bytes.Buffer
|
||||
)
|
||||
|
||||
switch len(command) {
|
||||
case 1:
|
||||
cmd = exec.Command(command[0], "") //nolint: gosec
|
||||
default:
|
||||
cmd = exec.Command(command[0], command[1:]...) //nolint: gosec
|
||||
}
|
||||
|
||||
cmd.Dir = "/"
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
err := cmd.Run()
|
||||
|
||||
if err != nil {
|
||||
if stdout.String() != "" {
|
||||
log.Printf("Unable to run '%s': %s, %s", strings.Join(command, " "), err, stdout.String())
|
||||
} else {
|
||||
log.Printf("Unable to run '%s': %s", strings.Join(command, " "), err)
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
if stderr.String() != "" {
|
||||
log.Printf("%s: %s", strings.Join(command, " "), stderr.String())
|
||||
}
|
||||
|
||||
return strings.TrimRight(stdout.String(), "\n")
|
||||
}
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
|
||||
@@ -51,17 +51,11 @@ func (c *MyConfig) ParseStdin() {
|
||||
continue
|
||||
}
|
||||
|
||||
for i := 0; i < len(buf); i++ {
|
||||
if strings.HasPrefix(buf, "{") {
|
||||
break
|
||||
}
|
||||
|
||||
buf = buf[1:]
|
||||
}
|
||||
|
||||
if len(buf) == 0 {
|
||||
log.Print("String from stdin has zero length, skipping")
|
||||
buf = strings.TrimLeftFunc(buf, func(r rune) bool {
|
||||
return r != '{'
|
||||
})
|
||||
|
||||
if !strings.HasPrefix(buf, "{") {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -116,18 +110,24 @@ func (c *MyConfig) ParseStdin() {
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
case app.Name != "" && e.Name == app.Name:
|
||||
prg := append([]string{}, app.Cmd)
|
||||
prg = append(prg, app.Args...)
|
||||
|
||||
c.Channels.RunChan <- prg
|
||||
|
||||
break
|
||||
case app.Instance != "" && e.Instance == app.Instance:
|
||||
prg := append([]string{}, app.Cmd)
|
||||
prg = append(prg, app.Args...)
|
||||
|
||||
c.Channels.RunChan <- prg
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -11,8 +12,8 @@ import (
|
||||
func (c *MyConfig) UpdateVPNStatus() {
|
||||
var (
|
||||
vpnCStatus string
|
||||
tcpCheck string
|
||||
vpnCheck string
|
||||
b strings.Builder
|
||||
InitialDelay = 100 * time.Millisecond
|
||||
LoopIterationDelay = 3 * time.Second
|
||||
Delay = InitialDelay
|
||||
@@ -27,36 +28,47 @@ func (c *MyConfig) UpdateVPNStatus() {
|
||||
|
||||
if c.VPNFileCheck() {
|
||||
if c.Vpn.UpColor == "" {
|
||||
vpnCheck = `⍋`
|
||||
b.WriteRune('⍋')
|
||||
} else {
|
||||
vpnCheck = fmt.Sprintf(`<span foreground="%s">⍋</span>`, c.Vpn.UpColor)
|
||||
b.WriteString("<span foreground=\"")
|
||||
b.WriteString(c.Vpn.UpColor)
|
||||
b.WriteString("\">⍋</span>")
|
||||
}
|
||||
} else {
|
||||
if c.Vpn.DownColor == "" {
|
||||
vpnCheck = `⍒`
|
||||
b.WriteRune('⍒')
|
||||
} else {
|
||||
vpnCheck = fmt.Sprintf(`<span foreground="%s">⍒</span>`, c.Vpn.DownColor)
|
||||
b.WriteString("<span foreground=\"")
|
||||
b.WriteString(c.Vpn.DownColor)
|
||||
b.WriteString("\">⍒</span>")
|
||||
}
|
||||
}
|
||||
|
||||
vpnCheck = b.String()
|
||||
b.Reset()
|
||||
|
||||
if c.Vpn.TCPCheck.Enabled {
|
||||
if c.VPNTCPCheck() {
|
||||
if c.Vpn.UpColor == "" {
|
||||
tcpCheck = `✔`
|
||||
b.WriteRune('✔')
|
||||
} else {
|
||||
tcpCheck = fmt.Sprintf(`<span foreground="%s">✔</span>`, c.Vpn.UpColor)
|
||||
b.WriteString("<span foreground=\"")
|
||||
b.WriteString(c.Vpn.UpColor)
|
||||
b.WriteString("\">✔</span>")
|
||||
}
|
||||
} else {
|
||||
if c.Vpn.DownColor == "" {
|
||||
tcpCheck = `✘`
|
||||
b.WriteRune('✘')
|
||||
} else {
|
||||
tcpCheck = fmt.Sprintf(`<span foreground="%s">✘</span>`, c.Vpn.DownColor)
|
||||
b.WriteString("<span foreground=\"")
|
||||
b.WriteString(c.Vpn.DownColor)
|
||||
b.WriteString("\">✘</span>")
|
||||
}
|
||||
}
|
||||
|
||||
vpnCStatus = fmt.Sprintf("VPN:%s:%s", vpnCheck, tcpCheck)
|
||||
vpnCStatus = "VPN:" + vpnCheck + ":" + b.String()
|
||||
} else {
|
||||
vpnCStatus = fmt.Sprintf("VPN:%s", vpnCheck)
|
||||
vpnCStatus = "VPN:" + vpnCheck
|
||||
}
|
||||
|
||||
if c.Values.VPNStatus != vpnCStatus {
|
||||
@@ -66,11 +78,11 @@ func (c *MyConfig) UpdateVPNStatus() {
|
||||
}
|
||||
}
|
||||
|
||||
// VPNTCPCheck intended to check arbitrary service inside vpn segment, to indicate that openvpn sevice not stoned.
|
||||
// VPNTCPCheck intended to check arbitrary service inside vpn segment, to indicate that openvpn service not stoned.
|
||||
func (c *MyConfig) VPNTCPCheck() bool {
|
||||
conn, err := net.DialTimeout(
|
||||
conn, err := net.DialTimeout( //nolint: noctx
|
||||
"tcp",
|
||||
fmt.Sprintf("%s:%d", c.Vpn.TCPCheck.Host, c.Vpn.TCPCheck.Port),
|
||||
fmt.Sprintf("%s:%d", c.Vpn.TCPCheck.Host, c.Vpn.TCPCheck.Port), //nolint: hostport
|
||||
time.Second*time.Duration(c.Vpn.TCPCheck.Timeout),
|
||||
)
|
||||
|
||||
@@ -100,3 +112,5 @@ func (c *MyConfig) VPNFileCheck() bool {
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||
|
||||
Reference in New Issue
Block a user