Compare commits
45 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 | ||
|
|
757fb5e57e | ||
|
|
6b81991ebb |
740
.golangci.yml
740
.golangci.yml
@@ -14,23 +14,29 @@ linters:
|
|||||||
- contextcheck
|
- contextcheck
|
||||||
- decorder
|
- decorder
|
||||||
- durationcheck
|
- durationcheck
|
||||||
- err113
|
|
||||||
- errcheck
|
- errcheck
|
||||||
- errchkjson
|
- errchkjson
|
||||||
- errorlint
|
- errorlint
|
||||||
|
- exptostd
|
||||||
- ginkgolinter
|
- ginkgolinter
|
||||||
- gocheckcompilerdirectives
|
- gocheckcompilerdirectives
|
||||||
- gocritic
|
- gocritic
|
||||||
|
- godoclint
|
||||||
- godot
|
- godot
|
||||||
|
- godox
|
||||||
|
- goprintffuncname
|
||||||
- gosec
|
- gosec
|
||||||
- gosmopolitan
|
- gosmopolitan
|
||||||
- govet
|
- govet
|
||||||
- grouper
|
- grouper
|
||||||
- importas
|
- importas
|
||||||
- ineffassign
|
- ineffassign
|
||||||
|
- intrange
|
||||||
- ireturn
|
- ireturn
|
||||||
- makezero
|
- makezero
|
||||||
- mirror
|
- mirror
|
||||||
|
- misspell
|
||||||
|
- modernize
|
||||||
- nakedret
|
- nakedret
|
||||||
- nilerr
|
- nilerr
|
||||||
- nilnil
|
- nilnil
|
||||||
@@ -38,6 +44,7 @@ linters:
|
|||||||
- noctx
|
- noctx
|
||||||
- nolintlint
|
- nolintlint
|
||||||
- nonamedreturns
|
- nonamedreturns
|
||||||
|
- perfsprint
|
||||||
- predeclared
|
- predeclared
|
||||||
- promlinter
|
- promlinter
|
||||||
- reassign
|
- reassign
|
||||||
@@ -46,14 +53,731 @@ linters:
|
|||||||
- staticcheck
|
- staticcheck
|
||||||
- unconvert
|
- unconvert
|
||||||
- unused
|
- unused
|
||||||
|
- usestdlibvars
|
||||||
- wastedassign
|
- wastedassign
|
||||||
- whitespace
|
- wsl_v5
|
||||||
- wsl
|
|
||||||
settings:
|
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:
|
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:
|
exclusions:
|
||||||
generated: lax
|
generated: lax
|
||||||
presets:
|
presets:
|
||||||
@@ -62,8 +786,6 @@ linters:
|
|||||||
- legacy
|
- legacy
|
||||||
- std-error-handling
|
- std-error-handling
|
||||||
paths:
|
paths:
|
||||||
- data
|
|
||||||
- vendor
|
|
||||||
- third_party$
|
- third_party$
|
||||||
- builtin$
|
- builtin$
|
||||||
- examples$
|
- examples$
|
||||||
@@ -74,8 +796,6 @@ formatters:
|
|||||||
exclusions:
|
exclusions:
|
||||||
generated: lax
|
generated: lax
|
||||||
paths:
|
paths:
|
||||||
- data
|
|
||||||
- vendor
|
|
||||||
- third_party$
|
- third_party$
|
||||||
- builtin$
|
- builtin$
|
||||||
- examples$
|
- examples$
|
||||||
|
|||||||
10
Makefile
10
Makefile
@@ -4,6 +4,7 @@ BUILDOPTS=-ldflags="-s -w" -a -gcflags=all=-l -trimpath -buildvcs=false
|
|||||||
|
|
||||||
BINARY=i3status-go
|
BINARY=i3status-go
|
||||||
TEST1=battery-test
|
TEST1=battery-test
|
||||||
|
TEST2=cmdrun-test
|
||||||
|
|
||||||
## Use calssic targets where first one is deafult target
|
## Use calssic targets where first one is deafult target
|
||||||
all: clean build
|
all: clean build
|
||||||
@@ -16,15 +17,18 @@ battery-test:
|
|||||||
rm -rf ${TEST1}
|
rm -rf ${TEST1}
|
||||||
go build ${BUILDOPTS} -o ${TEST1} ./cmd/${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
|
## Remove binary with golang compiler' means
|
||||||
clean:
|
clean:
|
||||||
rm -rf ${BINARY} ${TEST1}
|
rm -rf ${BINARY} ${TEST1} ${TEST2}
|
||||||
|
|
||||||
|
|
||||||
## Misc target, for development purposes. Updates vendored libs, brutal way.
|
## Misc target, for development purposes. Updates vendored libs, brutal way.
|
||||||
upgrade:
|
upgrade:
|
||||||
$(RM) -r vendor
|
$(RM) -r vendor
|
||||||
go get -u -t -tool ./...
|
go get -u -t ./...
|
||||||
go mod tidy
|
go mod tidy
|
||||||
go mod vendor
|
go mod vendor
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,12 @@ It is i3bar text generator.
|
|||||||
* PulseAudio volume indicator, can adjust master volume too
|
* PulseAudio volume indicator, can adjust master volume too
|
||||||
* Clock
|
* Clock
|
||||||
* Cron jobs (intended to use for show periodic desktop notifications but not limited to)
|
* 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
|
## 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
|
This application was tested to compile with go v1.24.
|
||||||
sure).
|
|
||||||
All you need is go lang compiler and gnu make utility. Invoke
|
All you need is go lang compiler and gnu make utility. Invoke
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// Package main simple test for battery funtionality.
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -20,3 +21,5 @@ func main() {
|
|||||||
time.Sleep(1 * time.Second)
|
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.
|
// Default text and *block* border colors. If not set #3e78fd is used.
|
||||||
"color" : "#3e78fd",
|
"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",
|
"background" : "#000000",
|
||||||
|
|
||||||
// Can be omitted, then Liberation Mono will be used.
|
// Can be omitted, then Liberation Mono will be used.
|
||||||
@@ -518,6 +518,15 @@
|
|||||||
"battery": {
|
"battery": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
|
|
||||||
|
// Valid only on linux, where we have mounted sysfs and /sys/class/power_supply/BAT0/capacity available
|
||||||
|
"use_sysfs": false,
|
||||||
|
|
||||||
|
// it is possible to set files here, if none set, /sys/class/power_supply/BAT0/capacity will be taken.
|
||||||
|
"sysfs_files": [
|
||||||
|
"/sys/class/power_supply/BAT0/capacity",
|
||||||
|
"/sys/class/power_supply/HIDP0/capacity"
|
||||||
|
],
|
||||||
|
|
||||||
// If omitted set to default color defined up here.
|
// If omitted set to default color defined up here.
|
||||||
"color": "#3e78fd",
|
"color": "#3e78fd",
|
||||||
|
|
||||||
@@ -693,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.
|
// Whether to display Application Buttons.
|
||||||
"app_buttons": {
|
"app_buttons": {
|
||||||
"enabled": true,
|
"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.
|
// Re-define separator parameters for net-if block here.
|
||||||
"separator": {
|
"separator": {
|
||||||
"left": {
|
"left": {
|
||||||
@@ -740,31 +834,36 @@
|
|||||||
// ‘smaller’ or ‘larger’. If omitted set to default font size defined for separator up here.
|
// ‘smaller’ or ‘larger’. If omitted set to default font size defined for separator up here.
|
||||||
"font_size": "medium"
|
"font_size": "medium"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Buttons - application launch "buttons"
|
// Buttons - application launch "buttons"
|
||||||
"apps": [
|
"apps": [
|
||||||
{
|
{
|
||||||
// Text dispalyed on button
|
// Text displayed on button, pango markup supported.
|
||||||
"full_text" : "📂",
|
"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",
|
"name" : "thunar",
|
||||||
// Command itself
|
// Command itself.
|
||||||
"cmd" : "thunar",
|
"cmd" : "thunar",
|
||||||
// Array of command args, optional
|
// Array of command args, optional.
|
||||||
"args": [ "." ],
|
"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$",
|
"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$",
|
"class": "^Thunar$",
|
||||||
// text color in html notation
|
// Text color in html notation.
|
||||||
"color": "#ffa500",
|
"color": "#ffa500",
|
||||||
// background color in html notation
|
// background color in html notation.
|
||||||
"background" : "#000000",
|
"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": "#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",
|
"border_active": "#3e78fd",
|
||||||
// Vertical line between objects on bar - if omitted true value is assumed by i3bar, but we set it to false
|
// 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.
|
// in that case. It is limitation of golang json parser.
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// Package main status string generator for i3bar.
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -8,6 +9,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
@@ -15,7 +17,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
//go:embed default-config.json
|
//go:embed default-config.json
|
||||||
var DefaultConfig []byte
|
var DefaultConfig []byte //nolint: godoclint, grouper, nolintlint
|
||||||
|
|
||||||
// Program entry point.
|
// Program entry point.
|
||||||
func main() {
|
func main() {
|
||||||
@@ -42,15 +44,11 @@ func main() {
|
|||||||
// Conf.Values.PA
|
// Conf.Values.PA
|
||||||
Conf.Values.SoundVolume = "🔊:0%"
|
Conf.Values.SoundVolume = "🔊:0%"
|
||||||
|
|
||||||
// TODO: Проставить дефолтные значения для глобальных переменных модулей.
|
Conf.Values.BatteryString = "<span color='" + Conf.Battery.Color +
|
||||||
Conf.Values.BatteryString = fmt.Sprintf(
|
"' background='" + Conf.Battery.Background +
|
||||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
"' font='" + Conf.Battery.SymbolFont +
|
||||||
Conf.Battery.Color,
|
"' size='" + Conf.Battery.SymbolFontSize +
|
||||||
Conf.Battery.Background,
|
"'>" + Conf.Battery.Symbol + "</span>"
|
||||||
Conf.Battery.SymbolFont,
|
|
||||||
Conf.Battery.SymbolFontSize,
|
|
||||||
Conf.Battery.Symbol,
|
|
||||||
)
|
|
||||||
|
|
||||||
Conf.Values.BatteryString += fmt.Sprintf(
|
Conf.Values.BatteryString += fmt.Sprintf(
|
||||||
"<span color='%s' background='%s' font='%s' size='%s'> ??%% •</span>",
|
"<span color='%s' background='%s' font='%s' size='%s'> ??%% •</span>",
|
||||||
@@ -84,6 +82,14 @@ func main() {
|
|||||||
Conf.Clock.FontSize,
|
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.Spawner()
|
||||||
go Conf.ParseStdin()
|
go Conf.ParseStdin()
|
||||||
go Conf.CleanZombies()
|
go Conf.CleanZombies()
|
||||||
@@ -96,6 +102,7 @@ func main() {
|
|||||||
|
|
||||||
// Kick signal handler
|
// Kick signal handler
|
||||||
go Conf.SigHandler()
|
go Conf.SigHandler()
|
||||||
|
|
||||||
signal.Notify(Conf.Channels.SigChan,
|
signal.Notify(Conf.Channels.SigChan,
|
||||||
syscall.SIGUSR1,
|
syscall.SIGUSR1,
|
||||||
syscall.SIGUSR2,
|
syscall.SIGUSR2,
|
||||||
@@ -143,6 +150,10 @@ func main() {
|
|||||||
go Conf.UpdateVPNStatus()
|
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
|
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
|
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
|
// TODO: впилить для первого и последнего батона separator
|
||||||
if Conf.AppButtons.Enabled {
|
if Conf.AppButtons.Enabled {
|
||||||
for num, app := range Conf.Apps {
|
for _, app := range Conf.Apps {
|
||||||
var b lib.I3BarOutBlock
|
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
|
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.Background = app.Background
|
||||||
b.Color = app.Color
|
b.Color = app.Color
|
||||||
b.Instance = app.Instance
|
b.Instance = app.Instance
|
||||||
@@ -217,42 +205,55 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if Conf.CPUTemp.Enabled {
|
if Conf.CPUTemp.Enabled {
|
||||||
var b lib.I3BarOutBlock
|
var (
|
||||||
|
b lib.I3BarOutBlock
|
||||||
|
sb strings.Builder
|
||||||
|
)
|
||||||
|
|
||||||
b.Color = Conf.CPUTemp.Color
|
b.Color = Conf.CPUTemp.Color
|
||||||
b.Background = Conf.CPUTemp.Background
|
b.Background = Conf.CPUTemp.Background
|
||||||
|
|
||||||
if Conf.CPUTemp.Separator.Left.Enabled {
|
if Conf.CPUTemp.Separator.Left.Enabled {
|
||||||
b.FullText = fmt.Sprintf(
|
sb.WriteString("<span color='")
|
||||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
sb.WriteString(Conf.CPUTemp.Separator.Left.Color)
|
||||||
Conf.CPUTemp.Separator.Left.Color,
|
sb.WriteString("' background='")
|
||||||
Conf.CPUTemp.Separator.Left.Background,
|
sb.WriteString(Conf.CPUTemp.Separator.Left.Background)
|
||||||
Conf.CPUTemp.Separator.Left.Font,
|
sb.WriteString("' font='")
|
||||||
Conf.CPUTemp.Separator.Left.FontSize,
|
sb.WriteString(Conf.CPUTemp.Separator.Left.Font)
|
||||||
Conf.CPUTemp.Separator.Left.Symbol,
|
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(
|
sb.WriteString("<span color='")
|
||||||
"<span color='%s' background='%s' font='%s' size='%s'>CPU: %d°</span>",
|
sb.WriteString(Conf.CPUTemp.Color)
|
||||||
Conf.CPUTemp.Color,
|
sb.WriteString("' background='")
|
||||||
Conf.CPUTemp.Background,
|
sb.WriteString(Conf.CPUTemp.Background)
|
||||||
Conf.CPUTemp.Font,
|
sb.WriteString("' font='")
|
||||||
Conf.CPUTemp.FontSize,
|
sb.WriteString(Conf.CPUTemp.Font)
|
||||||
Conf.Values.CPUTemperature,
|
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 {
|
if Conf.CPUTemp.Separator.Right.Enabled {
|
||||||
b.FullText += fmt.Sprintf(
|
sb.WriteString("<span color='")
|
||||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
sb.WriteString(Conf.CPUTemp.Separator.Right.Color)
|
||||||
Conf.CPUTemp.Separator.Right.Color,
|
sb.WriteString("' background='")
|
||||||
Conf.CPUTemp.Separator.Right.Background,
|
sb.WriteString(Conf.CPUTemp.Separator.Right.Background)
|
||||||
Conf.CPUTemp.Separator.Right.Font,
|
sb.WriteString("' font='")
|
||||||
Conf.CPUTemp.Separator.Right.FontSize,
|
sb.WriteString(Conf.CPUTemp.Separator.Right.Font)
|
||||||
Conf.CPUTemp.Separator.Right.Symbol,
|
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.Markup = "pango"
|
||||||
b.Separator = false
|
b.Separator = false
|
||||||
|
|
||||||
@@ -260,56 +261,66 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if Conf.Mem.Enabled {
|
if Conf.Mem.Enabled {
|
||||||
var b lib.I3BarOutBlock
|
var (
|
||||||
|
b lib.I3BarOutBlock
|
||||||
|
sb strings.Builder
|
||||||
|
)
|
||||||
|
|
||||||
b.Color = Conf.Mem.Color
|
b.Color = Conf.Mem.Color
|
||||||
b.Background = Conf.Mem.Background
|
b.Background = Conf.Mem.Background
|
||||||
|
|
||||||
if Conf.Mem.Separator.Left.Enabled {
|
if Conf.Mem.Separator.Left.Enabled {
|
||||||
b.FullText = fmt.Sprintf(
|
sb.WriteString("<span color='")
|
||||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
sb.WriteString(Conf.Mem.Separator.Left.Color)
|
||||||
Conf.Mem.Separator.Left.Color,
|
sb.WriteString("' background='")
|
||||||
Conf.Mem.Separator.Left.Background,
|
sb.WriteString(Conf.Mem.Separator.Left.Background)
|
||||||
Conf.Mem.Separator.Left.Font,
|
sb.WriteString("' font='")
|
||||||
Conf.Mem.Separator.Left.FontSize,
|
sb.WriteString(Conf.Mem.Separator.Left.Font)
|
||||||
Conf.Mem.Separator.Left.Symbol,
|
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 {
|
if Conf.Mem.ShowSwap {
|
||||||
b.FullText += fmt.Sprintf(
|
sb.WriteString("% SW:")
|
||||||
"<span color='%s' background='%s' font='%s' size='%s'>M:%d%% SHM:%dM SW:%dM</span>",
|
sb.WriteString(strconv.FormatUint(Conf.Values.Memory.Swap, 10))
|
||||||
Conf.Mem.Color,
|
sb.WriteString("M")
|
||||||
Conf.Mem.Background,
|
|
||||||
Conf.Mem.Font,
|
|
||||||
Conf.Mem.FontSize,
|
|
||||||
Conf.Values.Memory.Usedpct,
|
|
||||||
Conf.Values.Memory.Shared,
|
|
||||||
Conf.Values.Memory.Swap,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
b.FullText += fmt.Sprintf(
|
sb.WriteString("%")
|
||||||
"<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("</span>")
|
||||||
|
|
||||||
if Conf.Mem.Separator.Right.Enabled {
|
if Conf.Mem.Separator.Right.Enabled {
|
||||||
b.FullText += fmt.Sprintf(
|
sb.WriteString("<span color='")
|
||||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
sb.WriteString(Conf.Mem.Separator.Right.Color)
|
||||||
Conf.Mem.Separator.Right.Color,
|
sb.WriteString("' background='")
|
||||||
Conf.Mem.Separator.Right.Background,
|
sb.WriteString(Conf.Mem.Separator.Right.Background)
|
||||||
Conf.Mem.Separator.Right.Font,
|
sb.WriteString("' font='")
|
||||||
Conf.Mem.Separator.Right.FontSize,
|
sb.WriteString(Conf.Mem.Separator.Right.Font)
|
||||||
Conf.Mem.Separator.Right.Symbol,
|
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.Markup = "pango"
|
||||||
b.Separator = false
|
b.Separator = false
|
||||||
|
|
||||||
@@ -317,42 +328,55 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if Conf.LA.Enabled {
|
if Conf.LA.Enabled {
|
||||||
var b lib.I3BarOutBlock
|
var (
|
||||||
|
b lib.I3BarOutBlock
|
||||||
|
sb strings.Builder
|
||||||
|
)
|
||||||
|
|
||||||
b.Color = Conf.LA.Color
|
b.Color = Conf.LA.Color
|
||||||
b.Background = Conf.LA.Background
|
b.Background = Conf.LA.Background
|
||||||
|
|
||||||
if Conf.LA.Separator.Left.Enabled {
|
if Conf.LA.Separator.Left.Enabled {
|
||||||
b.FullText = fmt.Sprintf(
|
sb.WriteString("<span color='")
|
||||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
sb.WriteString(Conf.LA.Separator.Left.Color)
|
||||||
Conf.LA.Separator.Left.Color,
|
sb.WriteString("' background='")
|
||||||
Conf.LA.Separator.Left.Background,
|
sb.WriteString(Conf.LA.Separator.Left.Background)
|
||||||
Conf.LA.Separator.Left.Font,
|
sb.WriteString("' font='")
|
||||||
Conf.LA.Separator.Left.FontSize,
|
sb.WriteString(Conf.LA.Separator.Left.Font)
|
||||||
Conf.LA.Separator.Left.Symbol,
|
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(
|
sb.WriteString("<span color='")
|
||||||
"<span color='%s' background='%s' font='%s' size='%s'>LA:%s</span>",
|
sb.WriteString(Conf.LA.Color)
|
||||||
Conf.LA.Color,
|
sb.WriteString("' background='")
|
||||||
Conf.LA.Background,
|
sb.WriteString(Conf.LA.Background)
|
||||||
Conf.LA.Font,
|
sb.WriteString("' font='")
|
||||||
Conf.LA.FontSize,
|
sb.WriteString(Conf.LA.Font)
|
||||||
Conf.Values.La,
|
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 {
|
if Conf.LA.Separator.Right.Enabled {
|
||||||
b.FullText += fmt.Sprintf(
|
sb.WriteString("<span color='")
|
||||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
sb.WriteString(Conf.LA.Separator.Right.Color)
|
||||||
Conf.LA.Separator.Right.Color,
|
sb.WriteString("' background='")
|
||||||
Conf.LA.Separator.Right.Background,
|
sb.WriteString(Conf.LA.Separator.Right.Background)
|
||||||
Conf.LA.Separator.Right.Font,
|
sb.WriteString("' font='")
|
||||||
Conf.LA.Separator.Right.FontSize,
|
sb.WriteString(Conf.LA.Separator.Right.Font)
|
||||||
Conf.LA.Separator.Right.Symbol,
|
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.Markup = "pango"
|
||||||
b.Separator = false
|
b.Separator = false
|
||||||
|
|
||||||
@@ -519,44 +543,101 @@ func main() {
|
|||||||
j = append(j, b)
|
j = append(j, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
if Conf.Clock.Enabled {
|
if Conf.CmdRun.Enabled {
|
||||||
var b lib.I3BarOutBlock
|
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.Name = `wallclock`
|
||||||
b.Color = Conf.Clock.Color
|
b.Color = Conf.Clock.Color
|
||||||
b.Background = Conf.Clock.Background
|
b.Background = Conf.Clock.Background
|
||||||
|
|
||||||
if Conf.Clock.Separator.Left.Enabled {
|
if Conf.Clock.Separator.Left.Enabled {
|
||||||
b.FullText = fmt.Sprintf(
|
sb.WriteString("<span color='")
|
||||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
sb.WriteString(Conf.Clock.Separator.Left.Color)
|
||||||
Conf.Clock.Separator.Left.Color,
|
sb.WriteString("' background='")
|
||||||
Conf.Clock.Separator.Left.Background,
|
sb.WriteString(Conf.Clock.Separator.Left.Background)
|
||||||
Conf.Clock.Separator.Left.Font,
|
sb.WriteString("' font='")
|
||||||
Conf.Clock.Separator.Left.FontSize,
|
sb.WriteString(Conf.Clock.Separator.Left.Font)
|
||||||
Conf.Clock.Separator.Left.Symbol,
|
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(
|
sb.WriteString("<span color='")
|
||||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
sb.WriteString(Conf.Clock.Color)
|
||||||
Conf.Clock.Color,
|
sb.WriteString("' background='")
|
||||||
Conf.Clock.Background,
|
sb.WriteString(Conf.Clock.Background)
|
||||||
Conf.Clock.Font,
|
sb.WriteString("' font='")
|
||||||
Conf.Clock.FontSize,
|
sb.WriteString(Conf.Clock.Font)
|
||||||
Conf.Values.ClockTime,
|
sb.WriteString("' size='")
|
||||||
)
|
sb.WriteString(Conf.Clock.FontSize)
|
||||||
|
sb.WriteString("'>")
|
||||||
|
sb.WriteString(Conf.Values.ClockTime)
|
||||||
|
sb.WriteString("</span>")
|
||||||
|
|
||||||
if Conf.Clock.Separator.Right.Enabled {
|
if Conf.Clock.Separator.Right.Enabled {
|
||||||
b.FullText += fmt.Sprintf(
|
sb.WriteString("<span color='")
|
||||||
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
|
sb.WriteString(Conf.Clock.Separator.Right.Color)
|
||||||
Conf.Clock.Separator.Right.Color,
|
sb.WriteString("' background='")
|
||||||
Conf.Clock.Separator.Right.Background,
|
sb.WriteString(Conf.Clock.Separator.Right.Background)
|
||||||
Conf.Clock.Separator.Right.Font,
|
sb.WriteString("' font='")
|
||||||
Conf.Clock.Separator.Right.FontSize,
|
sb.WriteString(Conf.Clock.Separator.Right.Font)
|
||||||
Conf.Clock.Separator.Right.Symbol,
|
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.Markup = "pango"
|
||||||
b.Separator = false
|
b.Separator = false
|
||||||
|
|
||||||
@@ -585,3 +666,5 @@ func PrintToI3bar(c *lib.MyConfig) {
|
|||||||
fmt.Println(strings.TrimSuffix(buf.String(), "\n") + ",")
|
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,8 +1,14 @@
|
|||||||
|
// Package lib represents guts of i3status-go.
|
||||||
package lib
|
package lib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"math"
|
"math"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/distatus/battery"
|
"github.com/distatus/battery"
|
||||||
@@ -11,9 +17,6 @@ import (
|
|||||||
// UpdateBatteryInfo updates info about battery charge.
|
// UpdateBatteryInfo updates info about battery charge.
|
||||||
func (c *MyConfig) UpdateBatteryInfo() {
|
func (c *MyConfig) UpdateBatteryInfo() {
|
||||||
var (
|
var (
|
||||||
ch int
|
|
||||||
status string
|
|
||||||
Batts string
|
|
||||||
InitialDelay = 100 * time.Millisecond
|
InitialDelay = 100 * time.Millisecond
|
||||||
LoopIterationDelay = 5 * time.Second
|
LoopIterationDelay = 5 * time.Second
|
||||||
Delay = InitialDelay
|
Delay = InitialDelay
|
||||||
@@ -26,9 +29,90 @@ func (c *MyConfig) UpdateBatteryInfo() {
|
|||||||
ticker.Reset(Delay)
|
ticker.Reset(Delay)
|
||||||
}
|
}
|
||||||
|
|
||||||
batteries, _ := battery.GetAll()
|
var (
|
||||||
// In theory, this module should give for each entry its separate err, but in practice it gives
|
batteries = []*battery.Battery{}
|
||||||
// one single err for all entries, so we cannot detemine whist exatly entry errored.
|
Batts string
|
||||||
|
ch int
|
||||||
|
status string
|
||||||
|
)
|
||||||
|
|
||||||
|
if c.Battery.UseSysfs {
|
||||||
|
for _, file := range c.Battery.SysfsFiles {
|
||||||
|
var batt battery.Battery
|
||||||
|
|
||||||
|
_, err := os.Stat(file)
|
||||||
|
|
||||||
|
// If file exists.
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
var (
|
||||||
|
myCharge string
|
||||||
|
myStatus string
|
||||||
|
)
|
||||||
|
|
||||||
|
b, err := os.ReadFile(file)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Unable to read file %s: %s", file, err)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
myCharge = strings.TrimSpace(string(b))
|
||||||
|
|
||||||
|
statusFile := filepath.Dir(file) + "/status"
|
||||||
|
|
||||||
|
_, 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.TrimSpace(string(b))
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make stub battery class :) .
|
||||||
|
switch myStatus {
|
||||||
|
case "Charging":
|
||||||
|
batt.State.Raw = battery.Charging
|
||||||
|
case "Discharging":
|
||||||
|
batt.State.Raw = battery.Discharging
|
||||||
|
case "Empty":
|
||||||
|
batt.State.Raw = battery.Empty
|
||||||
|
case "Full":
|
||||||
|
batt.State.Raw = battery.Full
|
||||||
|
default:
|
||||||
|
batt.State.Raw = battery.Unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
ch, err := strconv.Atoi(myCharge)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Unable to convert string from file %s to integer", file)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
batt.Current = float64(ch)
|
||||||
|
|
||||||
|
batteries = append(batteries, &batt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
batteries, err = battery.GetAll()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Unable to get battery info: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
battsInfo string
|
battsInfo string
|
||||||
@@ -49,7 +133,11 @@ func (c *MyConfig) UpdateBatteryInfo() {
|
|||||||
|
|
||||||
// N.B. there can be case when battery is overcharged and shows >100%. It also can indicate that
|
// N.B. there can be case when battery is overcharged and shows >100%. It also can indicate that
|
||||||
// calibration data is out of date and battery should be re-calibrated.
|
// calibration data is out of date and battery should be re-calibrated.
|
||||||
|
if c.Battery.UseSysfs {
|
||||||
|
ch = int(b.Current)
|
||||||
|
} else {
|
||||||
ch = int(math.Round((b.Full - (b.Full - b.Current)) * (100 / b.Full)))
|
ch = int(math.Round((b.Full - (b.Full - b.Current)) * (100 / b.Full)))
|
||||||
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case ch <= 500 && ch >= 84:
|
case ch <= 500 && ch >= 84:
|
||||||
@@ -171,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.
|
// Collection is sync.Map, that stores arbitrary data.
|
||||||
type Collection struct {
|
type Collection struct {
|
||||||
items sync.Map
|
items sync.Map
|
||||||
close chan struct{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Item just interface for stoing any data.
|
// Item just interface for stoing any data.
|
||||||
@@ -17,9 +16,7 @@ type item struct {
|
|||||||
|
|
||||||
// NewCollection creates new instance of "collection".
|
// NewCollection creates new instance of "collection".
|
||||||
func NewCollection() *Collection {
|
func NewCollection() *Collection {
|
||||||
c := &Collection{ //nolint:exhaustruct
|
c := &Collection{}
|
||||||
close: make(chan struct{}),
|
|
||||||
}
|
|
||||||
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
@@ -32,9 +29,12 @@ func (collection *Collection) Get(key any) (any, bool) {
|
|||||||
return nil, false
|
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".
|
// 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) {
|
func (collection *Collection) Range(f func(key, value any) bool) {
|
||||||
fn := 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)
|
collection.items.Range(fn)
|
||||||
@@ -62,7 +65,6 @@ func (collection *Collection) Delete(key any) {
|
|||||||
|
|
||||||
// Close frees memory occupied by collection and deletes collection itself.
|
// Close frees memory occupied by collection and deletes collection itself.
|
||||||
func (collection *Collection) Close() {
|
func (collection *Collection) Close() {
|
||||||
collection.close <- struct{}{}
|
|
||||||
collection.items = sync.Map{}
|
collection.items = sync.Map{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,19 +14,22 @@ import (
|
|||||||
p "github.com/mafik/pulseaudio"
|
p "github.com/mafik/pulseaudio"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
// I3BarOutBlock is structure element for I3BarOut, it represents i3bar output json block format.
|
// I3BarOutBlock is structure element for I3BarOut, it represents i3bar output json block format.
|
||||||
type I3BarOutBlock struct {
|
I3BarOutBlock struct {
|
||||||
FullText string `json:"full_text"`
|
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"`
|
ShortText string `json:"short_text,omitempty"`
|
||||||
Color string `json:"color,omitempty"`
|
Color string `json:"color,omitempty"`
|
||||||
Background string `json:"background,omitempty"`
|
Background string `json:"background,omitempty"`
|
||||||
|
Font string `json:"font,omitempty"`
|
||||||
|
FontSize string `json:"font_size,omitempty"`
|
||||||
Border string `json:"border,omitempty"`
|
Border string `json:"border,omitempty"`
|
||||||
BorderTop int `json:"border_top"`
|
BorderTop int `json:"border_top"`
|
||||||
BorderRight int `json:"border_right"`
|
BorderRight int `json:"border_right"`
|
||||||
BorderBottom int `json:"border_bottom"`
|
BorderBottom int `json:"border_bottom"`
|
||||||
BorderLeft int `json:"border_left"`
|
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"`
|
MinWidth string `json:"min_width,omitempty"`
|
||||||
Align string `json:"align,omitempty"`
|
Align string `json:"align,omitempty"`
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
@@ -37,27 +40,29 @@ type I3BarOutBlock struct {
|
|||||||
Markup string `json:"markup,omitempty"`
|
Markup string `json:"markup,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Separator struct {
|
// Separator usually is a bymbol that separates fields in i3 status string.
|
||||||
|
Separator struct {
|
||||||
Left struct {
|
Left struct {
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
|
||||||
Color string `json:"color,omitempty"`
|
Color string `json:"color,omitempty"`
|
||||||
Background string `json:"background,omitempty"`
|
Background string `json:"background,omitempty"`
|
||||||
Symbol string `json:"symbol,omitempty"`
|
Symbol string `json:"symbol,omitempty"`
|
||||||
Font string `json:"font,omitempty"`
|
Font string `json:"font,omitempty"`
|
||||||
FontSize string `json:"font_size,omitempty"`
|
FontSize string `json:"font_size,omitempty"`
|
||||||
} `json:"left,omitempty"`
|
Enabled bool `json:"enabled,omitempty"`
|
||||||
|
} `json:"left"`
|
||||||
|
|
||||||
Right struct {
|
Right struct {
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
|
||||||
Color string `json:"color,omitempty"`
|
Color string `json:"color,omitempty"`
|
||||||
Background string `json:"background,omitempty"`
|
Background string `json:"background,omitempty"`
|
||||||
Symbol string `json:"symbol,omitempty"`
|
Symbol string `json:"symbol,omitempty"`
|
||||||
Font string `json:"font,omitempty"`
|
Font string `json:"font,omitempty"`
|
||||||
FontSize string `json:"font_size,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 {
|
Values struct {
|
||||||
PrintOutput bool
|
PrintOutput bool
|
||||||
CPUTemperature int64
|
CPUTemperature int64
|
||||||
@@ -69,6 +74,7 @@ type MyConfig struct {
|
|||||||
La string
|
La string
|
||||||
PA *p.Client
|
PA *p.Client
|
||||||
SoundVolume string
|
SoundVolume string
|
||||||
|
RunCommandOutput string
|
||||||
}
|
}
|
||||||
|
|
||||||
Channels struct {
|
Channels struct {
|
||||||
@@ -79,21 +85,22 @@ type MyConfig struct {
|
|||||||
RunChan chan []string
|
RunChan chan []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default text color
|
// Color default text color.
|
||||||
Color string `json:"color,omitempty"`
|
Color string `json:"color,omitempty"`
|
||||||
|
|
||||||
// Default background color
|
// Background default background color.
|
||||||
Background string `json:"background,omitempty"`
|
Background string `json:"background,omitempty"`
|
||||||
|
|
||||||
// Default text font
|
// Font default text font.
|
||||||
Font string `json:"font,omitempty"`
|
Font string `json:"font,omitempty"`
|
||||||
|
|
||||||
// Default text font size
|
// FontSize default text font size.
|
||||||
FontSize string `json:"font_size,omitempty"`
|
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 {
|
LA struct {
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
Enabled bool `json:"enabled,omitempty"`
|
||||||
Color string `json:"color,omitempty"`
|
Color string `json:"color,omitempty"`
|
||||||
@@ -101,9 +108,9 @@ type MyConfig struct {
|
|||||||
Font string `json:"font,omitempty"`
|
Font string `json:"font,omitempty"`
|
||||||
FontSize string `json:"font_size,omitempty"`
|
FontSize string `json:"font_size,omitempty"`
|
||||||
Separator Separator `json:"separator,omitempty"`
|
Separator Separator `json:"separator,omitempty"`
|
||||||
} `json:"la,omitempty"`
|
} `json:"la"`
|
||||||
|
|
||||||
// Mem plugin
|
// Mem plugin.
|
||||||
Mem struct {
|
Mem struct {
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
Enabled bool `json:"enabled,omitempty"`
|
||||||
Color string `json:"color,omitempty"`
|
Color string `json:"color,omitempty"`
|
||||||
@@ -112,8 +119,9 @@ type MyConfig struct {
|
|||||||
FontSize string `json:"font_size,omitempty"`
|
FontSize string `json:"font_size,omitempty"`
|
||||||
ShowSwap bool `json:"show_swap,omitempty"`
|
ShowSwap bool `json:"show_swap,omitempty"`
|
||||||
Separator Separator `json:"separator,omitempty"`
|
Separator Separator `json:"separator,omitempty"`
|
||||||
} `json:"mem,omitempty"`
|
} `json:"mem"`
|
||||||
|
|
||||||
|
// Clock plugin.
|
||||||
Clock struct {
|
Clock struct {
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
Enabled bool `json:"enabled,omitempty"`
|
||||||
Color string `json:"color,omitempty"`
|
Color string `json:"color,omitempty"`
|
||||||
@@ -125,16 +133,19 @@ type MyConfig struct {
|
|||||||
LeftClick struct {
|
LeftClick struct {
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
Enabled bool `json:"enabled,omitempty"`
|
||||||
Cmd []string `json:"cmd,omitempty"`
|
Cmd []string `json:"cmd,omitempty"`
|
||||||
} `json:"left_click,omitempty"`
|
} `json:"left_click"`
|
||||||
|
|
||||||
RightClick struct {
|
RightClick struct {
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
Enabled bool `json:"enabled,omitempty"`
|
||||||
Cmd []string `json:"cmd,omitempty"`
|
Cmd []string `json:"cmd,omitempty"`
|
||||||
} `json:"right_click,omitempty"`
|
} `json:"right_click"`
|
||||||
} `json:"clock,omitempty"`
|
} `json:"clock"`
|
||||||
|
|
||||||
|
// Battery plugin.
|
||||||
Battery struct {
|
Battery struct {
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
Enabled bool `json:"enabled,omitempty"`
|
||||||
|
UseSysfs bool `json:"use_sysfs,omitempty"`
|
||||||
|
SysfsFiles []string `json:"sysfs_files,omitempty"`
|
||||||
Color string `json:"color,omitempty"`
|
Color string `json:"color,omitempty"`
|
||||||
Background string `json:"background,omitempty"`
|
Background string `json:"background,omitempty"`
|
||||||
Font string `json:"font,omitempty"`
|
Font string `json:"font,omitempty"`
|
||||||
@@ -148,11 +159,12 @@ type MyConfig struct {
|
|||||||
Empty string `json:"empty,omitempty"`
|
Empty string `json:"empty,omitempty"`
|
||||||
AlmostFull string `json:"almost_full,omitempty"`
|
AlmostFull string `json:"almost_full,omitempty"`
|
||||||
AlmostEmpty string `json:"almost_empty,omitempty"`
|
AlmostEmpty string `json:"almost_empty,omitempty"`
|
||||||
} `json:"charge_color,omitempty"`
|
} `json:"charge_color"`
|
||||||
|
|
||||||
Separator Separator `json:"separator,omitempty"`
|
Separator Separator `json:"separator,omitempty"`
|
||||||
} `json:"battery,omitempty"`
|
} `json:"battery"`
|
||||||
|
|
||||||
|
// CPUTemp plugin.
|
||||||
CPUTemp struct {
|
CPUTemp struct {
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
Enabled bool `json:"enabled,omitempty"`
|
||||||
Color string `json:"color,omitempty"`
|
Color string `json:"color,omitempty"`
|
||||||
@@ -162,8 +174,9 @@ type MyConfig struct {
|
|||||||
Separator Separator `json:"separator,omitempty"`
|
Separator Separator `json:"separator,omitempty"`
|
||||||
|
|
||||||
File []string `json:"file,omitempty"`
|
File []string `json:"file,omitempty"`
|
||||||
} `json:"cpu_temp,omitempty"`
|
} `json:"cpu_temp"`
|
||||||
|
|
||||||
|
// Vpn plugin.
|
||||||
Vpn struct {
|
Vpn struct {
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
Enabled bool `json:"enabled,omitempty"`
|
||||||
Color string `json:"color,omitempty"`
|
Color string `json:"color,omitempty"`
|
||||||
@@ -174,16 +187,17 @@ type MyConfig struct {
|
|||||||
MtimeThreshold int `json:"mtime_threshold,omitempty"`
|
MtimeThreshold int `json:"mtime_threshold,omitempty"`
|
||||||
DownColor string `json:"down_color,omitempty"`
|
DownColor string `json:"down_color,omitempty"`
|
||||||
UpColor string `json:"up_color,omitempty"`
|
UpColor string `json:"up_color,omitempty"`
|
||||||
Separator Separator `json:"separator,omitempty"`
|
Separator Separator `json:"separator"`
|
||||||
|
|
||||||
TCPCheck struct {
|
TCPCheck struct {
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
Enabled bool `json:"enabled,omitempty"`
|
||||||
Host string `json:"host,omitempty"`
|
Host string `json:"host,omitempty"`
|
||||||
Port int `json:"port,omitempty"`
|
Port int `json:"port,omitempty"`
|
||||||
Timeout int `json:"timeout,omitempty"`
|
Timeout int `json:"timeout,omitempty"`
|
||||||
} `json:"tcp_check,omitempty"`
|
} `json:"tcp_check"`
|
||||||
} `json:"vpn,omitempty"`
|
} `json:"vpn"`
|
||||||
|
|
||||||
|
// SimpleVolumePa plugin.
|
||||||
SimpleVolumePa struct {
|
SimpleVolumePa struct {
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
Enabled bool `json:"enabled,omitempty"`
|
||||||
Color string `json:"color,omitempty"`
|
Color string `json:"color,omitempty"`
|
||||||
@@ -201,8 +215,9 @@ type MyConfig struct {
|
|||||||
WheelUp int `json:"wheel_up,omitempty"`
|
WheelUp int `json:"wheel_up,omitempty"`
|
||||||
WheelDown int `json:"wheel_down,omitempty"`
|
WheelDown int `json:"wheel_down,omitempty"`
|
||||||
MaxVolumeLimit int `json:"max_volume_limit,omitempty"`
|
MaxVolumeLimit int `json:"max_volume_limit,omitempty"`
|
||||||
} `json:"simple-volume-pa,omitempty"`
|
} `json:"simple-volume-pa"`
|
||||||
|
|
||||||
|
// NrtIf plugin.
|
||||||
NetIf struct {
|
NetIf struct {
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
Enabled bool `json:"enabled,omitempty"`
|
||||||
DownColor string `json:"down_color,omitempty"`
|
DownColor string `json:"down_color,omitempty"`
|
||||||
@@ -216,9 +231,10 @@ type MyConfig struct {
|
|||||||
If []struct {
|
If []struct {
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
Dir string `json:"dir,omitempty"`
|
Dir string `json:"dir,omitempty"`
|
||||||
} `json:"if,omitempty"`
|
} `json:"if"`
|
||||||
} `json:"net-if,omitempty"`
|
} `json:"net-if"`
|
||||||
|
|
||||||
|
// Cron plugin.
|
||||||
Cron struct {
|
Cron struct {
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
Enabled bool `json:"enabled,omitempty"`
|
||||||
TimeZone string `json:"timezone,omitempty"`
|
TimeZone string `json:"timezone,omitempty"`
|
||||||
@@ -226,14 +242,33 @@ type MyConfig struct {
|
|||||||
Tasks []struct {
|
Tasks []struct {
|
||||||
Time string `json:"time,omitempty"`
|
Time string `json:"time,omitempty"`
|
||||||
Cmd []string `json:"cmd,omitempty"`
|
Cmd []string `json:"cmd,omitempty"`
|
||||||
} `json:"tasks,omitempty"`
|
} `json:"tasks"`
|
||||||
} `json:"cron,omitempty"`
|
} `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 {
|
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"`
|
Enabled bool `json:"enabled,omitempty"`
|
||||||
Separator Separator `json:"separator,omitempty"`
|
Separator Separator `json:"separator,omitempty"`
|
||||||
} `json:"app_buttons,omitempty"`
|
} `json:"app_buttons"`
|
||||||
|
|
||||||
|
// Apps descriptions for AppButtons plugin.
|
||||||
Apps []struct {
|
Apps []struct {
|
||||||
FullText string `json:"full_text,omitempty"`
|
FullText string `json:"full_text,omitempty"`
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
@@ -243,14 +278,17 @@ type MyConfig struct {
|
|||||||
Class string `json:"class,omitempty"`
|
Class string `json:"class,omitempty"`
|
||||||
Color string `json:"color,omitempty"`
|
Color string `json:"color,omitempty"`
|
||||||
Background string `json:"background,omitempty"`
|
Background string `json:"background,omitempty"`
|
||||||
|
Font string `json:"font,omitempty"`
|
||||||
|
FontSize string `json:"font_size,omitempty"`
|
||||||
Border string `json:"border,omitempty"`
|
Border string `json:"border,omitempty"`
|
||||||
BorderActive string `json:"border_active,omitempty"`
|
BorderActive string `json:"border_active,omitempty"`
|
||||||
Separator bool `json:"separator,omitempty"`
|
Separator bool `json:"separator,omitempty"`
|
||||||
SeparatorBlockWidth int `json:"separator_block_width,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.
|
// is located.
|
||||||
func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
||||||
var (
|
var (
|
||||||
@@ -449,6 +487,30 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
|||||||
|
|
||||||
if sampleConfig.LA.FontSize == "" {
|
if sampleConfig.LA.FontSize == "" {
|
||||||
sampleConfig.LA.FontSize = sampleConfig.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 == "" {
|
if sampleConfig.LA.Separator.Left.Color == "" {
|
||||||
@@ -503,22 +565,6 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
|||||||
sampleConfig.LA.Separator.Right.Background = sampleConfig.Separator.Right.Background
|
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 == "" {
|
if sampleConfig.LA.Separator.Right.Symbol == "" {
|
||||||
sampleConfig.LA.Separator.Right.Symbol = sampleConfig.Separator.Right.Symbol
|
sampleConfig.LA.Separator.Right.Symbol = sampleConfig.Separator.Right.Symbol
|
||||||
}
|
}
|
||||||
@@ -569,6 +615,30 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
|||||||
|
|
||||||
if sampleConfig.Mem.FontSize == "" {
|
if sampleConfig.Mem.FontSize == "" {
|
||||||
sampleConfig.Mem.FontSize = sampleConfig.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 == "" {
|
if sampleConfig.Mem.Separator.Left.Color == "" {
|
||||||
@@ -673,6 +743,30 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
|||||||
|
|
||||||
if sampleConfig.Clock.FontSize == "" {
|
if sampleConfig.Clock.FontSize == "" {
|
||||||
sampleConfig.Clock.FontSize = sampleConfig.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 {
|
if sampleConfig.Clock.Separator.Left.Enabled {
|
||||||
@@ -765,19 +859,28 @@ 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 {
|
if len(sampleConfig.Clock.LeftClick.Cmd) == 0 {
|
||||||
sampleConfig.Clock.LeftClick.Cmd = append(sampleConfig.Clock.LeftClick.Cmd, "true")
|
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 {
|
if len(sampleConfig.Clock.RightClick.Cmd) == 0 {
|
||||||
sampleConfig.Clock.RightClick.Cmd = append(sampleConfig.Clock.RightClick.Cmd, "true")
|
sampleConfig.Clock.RightClick.Cmd = append(sampleConfig.Clock.RightClick.Cmd, "true")
|
||||||
}
|
}
|
||||||
|
|
||||||
// sampleConfig.Battery.Enabled 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(
|
||||||
|
sampleConfig.Battery.SysfsFiles,
|
||||||
|
"/sys/class/power_supply/BAT0/capacity",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if sampleConfig.Battery.Color == "" {
|
if sampleConfig.Battery.Color == "" {
|
||||||
sampleConfig.Battery.Color = sampleConfig.Color
|
sampleConfig.Battery.Color = sampleConfig.Color
|
||||||
}
|
}
|
||||||
@@ -792,6 +895,30 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
|||||||
|
|
||||||
if sampleConfig.Battery.FontSize == "" {
|
if sampleConfig.Battery.FontSize == "" {
|
||||||
sampleConfig.Battery.FontSize = sampleConfig.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 == "" {
|
if sampleConfig.Battery.Symbol == "" {
|
||||||
@@ -803,13 +930,37 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if sampleConfig.Battery.SymbolFontSize == "" {
|
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.SymbolFontSize = sampleConfig.Battery.FontSize
|
||||||
}
|
}
|
||||||
|
|
||||||
// sampleConfig.Battery.ChargeColor.Full will be empty string if not set
|
if !matched {
|
||||||
// sampleConfig.Battery.ChargeColor.Empty will be empty string if not set
|
log.Printf(
|
||||||
// sampleConfig.Battery.ChargeColor.AlmostFull will be empty string if not set
|
"Unable to set sampleConfig.Battery.SymbolFontSize, fallback to %s",
|
||||||
// sampleConfig.Battery.ChargeColor.AlmostEmpty will be empty string if not set
|
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 == "" {
|
if sampleConfig.Battery.Separator.Left.Color == "" {
|
||||||
sampleConfig.Battery.Separator.Left.Color = sampleConfig.Separator.Left.Color
|
sampleConfig.Battery.Separator.Left.Color = sampleConfig.Separator.Left.Color
|
||||||
}
|
}
|
||||||
@@ -898,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 {
|
if len(sampleConfig.CPUTemp.File) == 0 {
|
||||||
sampleConfig.CPUTemp.Enabled = false
|
sampleConfig.CPUTemp.Enabled = false
|
||||||
}
|
}
|
||||||
@@ -919,6 +1070,30 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
|||||||
|
|
||||||
if sampleConfig.CPUTemp.FontSize == "" {
|
if sampleConfig.CPUTemp.FontSize == "" {
|
||||||
sampleConfig.CPUTemp.FontSize = sampleConfig.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 {
|
if sampleConfig.CPUTemp.Separator.Left.Enabled {
|
||||||
@@ -1009,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 == "" {
|
if sampleConfig.Vpn.StatusFile == "" {
|
||||||
sampleConfig.Vpn.Enabled = false
|
sampleConfig.Vpn.Enabled = false
|
||||||
}
|
}
|
||||||
@@ -1025,23 +1200,47 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if sampleConfig.Vpn.Font == "" {
|
if sampleConfig.Vpn.Font == "" {
|
||||||
sampleConfig.Vpn.FontSize = sampleConfig.Font
|
sampleConfig.Vpn.Font = sampleConfig.Font
|
||||||
}
|
}
|
||||||
|
|
||||||
if sampleConfig.Vpn.FontSize == "" {
|
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
|
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 {
|
if sampleConfig.Vpn.MtimeThreshold < 3 {
|
||||||
log.Printf("vpn.mtime_threshold not set, using 3")
|
log.Printf("vpn.mtime_threshold not set, using 3")
|
||||||
|
|
||||||
sampleConfig.Vpn.MtimeThreshold = 3
|
sampleConfig.Vpn.MtimeThreshold = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
// sampleConfig.Vpn.DownColor will be empty string if no value 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.UpColor will be empty string if no value set in config.
|
||||||
// sampleConfig.Vpn.TcpCheck.Enabled will false if not 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.Enabled {
|
||||||
if sampleConfig.Vpn.Separator.Left.Color == "" {
|
if sampleConfig.Vpn.Separator.Left.Color == "" {
|
||||||
@@ -1133,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.Port > 65535 {
|
||||||
if sampleConfig.Vpn.TCPCheck.Enabled {
|
if sampleConfig.Vpn.TCPCheck.Enabled {
|
||||||
log.Printf("vpn.tcp_check.port > 65535, disabling vpn.tcp_check.enabled")
|
log.Printf("vpn.tcp_check.port > 65535, disabling vpn.tcp_check.enabled")
|
||||||
@@ -1142,7 +1341,7 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
|||||||
sampleConfig.Vpn.TCPCheck.Enabled = false
|
sampleConfig.Vpn.TCPCheck.Enabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable plugin if value indaquate
|
// Disable plugin if value indaquate.
|
||||||
if sampleConfig.Vpn.TCPCheck.Host == "" {
|
if sampleConfig.Vpn.TCPCheck.Host == "" {
|
||||||
if sampleConfig.Vpn.TCPCheck.Enabled {
|
if sampleConfig.Vpn.TCPCheck.Enabled {
|
||||||
log.Printf("vpn.tcp_check.host not set, disabling vpn.tcp_check.enabled")
|
log.Printf("vpn.tcp_check.host not set, disabling vpn.tcp_check.enabled")
|
||||||
@@ -1159,7 +1358,7 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
|||||||
sampleConfig.Vpn.TCPCheck.Timeout = 3
|
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 == "" {
|
if sampleConfig.SimpleVolumePa.Color == "" {
|
||||||
sampleConfig.SimpleVolumePa.Color = sampleConfig.Color
|
sampleConfig.SimpleVolumePa.Color = sampleConfig.Color
|
||||||
}
|
}
|
||||||
@@ -1174,6 +1373,30 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
|||||||
|
|
||||||
if sampleConfig.SimpleVolumePa.FontSize == "" {
|
if sampleConfig.SimpleVolumePa.FontSize == "" {
|
||||||
sampleConfig.SimpleVolumePa.FontSize = sampleConfig.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 == "" {
|
if sampleConfig.SimpleVolumePa.Symbol == "" {
|
||||||
@@ -1186,6 +1409,30 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
|||||||
|
|
||||||
if sampleConfig.SimpleVolumePa.SymbolFontSize == "" {
|
if sampleConfig.SimpleVolumePa.SymbolFontSize == "" {
|
||||||
sampleConfig.SimpleVolumePa.SymbolFontSize = sampleConfig.SimpleVolumePa.FontSize
|
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 {
|
if sampleConfig.SimpleVolumePa.Step == 0 {
|
||||||
@@ -1308,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 {
|
if len(sampleConfig.Cron.Tasks) == 0 {
|
||||||
sampleConfig.Cron.Enabled = false
|
sampleConfig.Cron.Enabled = false
|
||||||
@@ -1318,7 +1565,7 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
|||||||
sampleConfig.Cron.TimeZone = "GMT+0"
|
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 {
|
if len(sampleConfig.NetIf.If) == 0 {
|
||||||
sampleConfig.NetIf.Enabled = false
|
sampleConfig.NetIf.Enabled = false
|
||||||
@@ -1346,6 +1593,29 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
|||||||
|
|
||||||
if sampleConfig.NetIf.FontSize == "" {
|
if sampleConfig.NetIf.FontSize == "" {
|
||||||
sampleConfig.NetIf.FontSize = sampleConfig.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 == "" {
|
if sampleConfig.NetIf.Separator.Left.Color == "" {
|
||||||
@@ -1435,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 == "" {
|
if sampleConfig.AppButtons.Separator.Left.Color == "" {
|
||||||
sampleConfig.AppButtons.Separator.Left.Color = sampleConfig.Separator.Left.Color
|
sampleConfig.AppButtons.Separator.Left.Color = sampleConfig.Separator.Left.Color
|
||||||
@@ -1531,34 +1980,68 @@ func ReadConf(defaultConfig []byte) (*MyConfig, error) {
|
|||||||
// app.Instance can be missing.
|
// app.Instance can be missing.
|
||||||
// app.Class can be missing.
|
// app.Class can be missing.
|
||||||
if app.Name == "" {
|
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.
|
// app.Args can be empty slice. In that case command will be run without aruments.
|
||||||
if app.Cmd == "" {
|
if app.Cmd == "" {
|
||||||
app.Cmd = "true"
|
// If command omitted it will be just /usr/bin/true.
|
||||||
|
sampleConfig.Apps[num].Cmd = "true"
|
||||||
}
|
}
|
||||||
|
|
||||||
if app.Color == "" {
|
if app.Color == "" {
|
||||||
app.Color = sampleConfig.Color
|
sampleConfig.Apps[num].Color = sampleConfig.AppButtons.Color
|
||||||
}
|
}
|
||||||
|
|
||||||
if app.Background == "" {
|
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 == "" {
|
if app.Border == "" {
|
||||||
app.Border = sampleConfig.Color
|
sampleConfig.Apps[num].Border = sampleConfig.AppButtons.Color
|
||||||
}
|
}
|
||||||
|
|
||||||
if app.BorderActive == "" {
|
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.Separator can be omitted, in that case it is false.
|
||||||
// app.SeparatorBlockWidth can be missing
|
// app.SeparatorBlockWidth can be missing.
|
||||||
if app.FullText == "" {
|
if app.FullText == "" {
|
||||||
app.FullText = fmt.Sprintf(" %d ", num)
|
sampleConfig.Apps[num].FullText = fmt.Sprintf(" %d ", num)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1580,3 +2063,5 @@ func LocateConfFile() (string, error) {
|
|||||||
|
|
||||||
return filepath.Dir(i3ConfigPath) + "/i3status-go.json", nil
|
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)
|
temperature = make([]int64, n)
|
||||||
tSum int64
|
tSum int64
|
||||||
tAvg int64
|
tAvg int64
|
||||||
|
validCount int
|
||||||
)
|
)
|
||||||
|
|
||||||
if Delay == InitialDelay {
|
if Delay == InitialDelay {
|
||||||
@@ -35,47 +36,50 @@ func (c *MyConfig) UpdateCPUTemperature() {
|
|||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Unable to open %s: %s", filename, err)
|
log.Printf("Unable to open %s: %s", filename, err)
|
||||||
} else {
|
continue
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
reader := bufio.NewReader(file)
|
reader := bufio.NewReader(file)
|
||||||
line, _, err := reader.ReadLine()
|
line, _, err := reader.ReadLine()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Unable to read from %s: %s", filename, err)
|
log.Printf("Unable to read from %s: %s", filename, err)
|
||||||
err = file.Close()
|
continue
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Unable to close %s: %s", filename, err)
|
|
||||||
}
|
}
|
||||||
} 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)
|
temp, err := strconv.ParseInt(string(line), 10, 32)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Unable to convert string to number from file %s: %s", filename, err)
|
log.Printf("Unable to convert string to number from file %s: %s", filename, err)
|
||||||
} else {
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if temp > 1000 {
|
if temp > 1000 {
|
||||||
temp /= 1000
|
temp /= 1000
|
||||||
}
|
}
|
||||||
|
|
||||||
temperature[i] = temp
|
temperature[i] = temp
|
||||||
}
|
validCount++
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(temperature) == 1 {
|
if validCount == 0 {
|
||||||
tAvg = temperature[0]
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if validCount == 1 {
|
||||||
|
for _, t := range temperature {
|
||||||
|
if t != 0 {
|
||||||
|
tAvg = t
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for _, t := range temperature {
|
for _, t := range temperature {
|
||||||
tSum += t
|
tSum += t
|
||||||
}
|
}
|
||||||
|
|
||||||
tAvg = tSum / int64(len(temperature))
|
tAvg = tSum / int64(validCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Values.CPUTemperature != tAvg {
|
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.
|
// 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.
|
// RunCron parses config part, related to cron tasks and kicks cron to run.
|
||||||
func (c MyConfig) RunCron() {
|
func (c MyConfig) RunCron() {
|
||||||
@@ -25,15 +27,12 @@ func (c MyConfig) RunCron() {
|
|||||||
_, err := myCron.NewJob(
|
_, err := myCron.NewJob(
|
||||||
gocron.CronJob(job.Time, false),
|
gocron.CronJob(job.Time, false),
|
||||||
gocron.NewTask(
|
gocron.NewTask(
|
||||||
// Сука, просто заспавнить бинарь, ну почему это надо делать через жопу-то?
|
|
||||||
any(
|
|
||||||
func() bool {
|
func() bool {
|
||||||
c.Channels.RunChan <- job.Cmd
|
c.Channels.RunChan <- job.Cmd
|
||||||
|
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -43,3 +42,5 @@ func (c MyConfig) RunCron() {
|
|||||||
|
|
||||||
myCron.Start()
|
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.
|
// UpdateI3WinList subsribes to all window-related events and send them to I3EventParser() for more detailed parsing.
|
||||||
func (c *MyConfig) UpdateI3WinList() {
|
func (c *MyConfig) UpdateI3WinList() {
|
||||||
// TODO: Здесь получить начальный список окон, управляемых i3wm (через GetTree()) и сложить их атрибутику в переменную WL
|
|
||||||
Tree, err := i3.GetTree()
|
Tree, err := i3.GetTree()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Unable to get list of windows: %s", err)
|
log.Printf("Unable to get list of windows: %s", err)
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ExtractProps(Tree.Root)
|
c.ExtractProps(Tree.Root)
|
||||||
|
|
||||||
|
c.Channels.UpdateReady <- true
|
||||||
|
|
||||||
i3wm := i3.Subscribe(i3.WindowEventType)
|
i3wm := i3.Subscribe(i3.WindowEventType)
|
||||||
|
|
||||||
for i3wm.Next() {
|
for i3wm.Next() {
|
||||||
@@ -105,9 +108,11 @@ func (c *MyConfig) I3EventParser(e *i3.WindowEvent) {
|
|||||||
|
|
||||||
// interfaceToUint превращает данный интерфейс в Uint64.
|
// interfaceToUint превращает данный интерфейс в Uint64.
|
||||||
// Если может, конечно :) .
|
// Если может, конечно :) .
|
||||||
func interfaceToUint64(iface interface{}) uint64 {
|
func interfaceToUint64(iface any) uint64 {
|
||||||
// А теперь мы начинаем дурдом, нам надо превратить ёбанный interface{} в []string
|
if iface == nil {
|
||||||
// Поскольку interface{} может быть чем угодно, перестрахуемся
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
if reflect.TypeOf(iface).Kind() == reflect.Uint64 {
|
if reflect.TypeOf(iface).Kind() == reflect.Uint64 {
|
||||||
return reflect.ValueOf(iface).Uint()
|
return reflect.ValueOf(iface).Uint()
|
||||||
}
|
}
|
||||||
@@ -152,18 +157,16 @@ func HasWindows(className string, instanceName string) bool {
|
|||||||
func FindWindowInstance(regexpStr string) bool {
|
func FindWindowInstance(regexpStr string) bool {
|
||||||
var found = false
|
var found = false
|
||||||
|
|
||||||
f := func(key any, value any) bool { //nolint: revive
|
re, err := regexp.Compile(regexpStr)
|
||||||
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.
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Unable to perform regexp match: %s", err)
|
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
|
if re.Match([]byte(keyStr)) { //nolint:mirror
|
||||||
found = true
|
found = true
|
||||||
|
|
||||||
@@ -183,18 +186,16 @@ func FindWindowInstance(regexpStr string) bool {
|
|||||||
func FindWindowClass(regexpStr string) bool {
|
func FindWindowClass(regexpStr string) bool {
|
||||||
var found = false
|
var found = false
|
||||||
|
|
||||||
f := func(key any, value any) bool { //nolint: revive
|
re, err := regexp.Compile(regexpStr)
|
||||||
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.
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Unable to perform regexp match: %s", err)
|
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
|
if re.Match([]byte(keyStr)) { //nolint:mirror
|
||||||
found = true
|
found = true
|
||||||
|
|
||||||
@@ -225,3 +226,5 @@ func (c *MyConfig) ExtractProps(n *i3.Node) {
|
|||||||
c.ExtractProps(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 {
|
} else {
|
||||||
switch strings.TrimSpace(string(operstate)) {
|
switch strings.TrimSpace(string(operstate)) {
|
||||||
case "up":
|
case "up":
|
||||||
StatusStr := fmt.Sprintf("<span foreground=\"%s\">⍋</span>", c.NetIf.UpColor)
|
statusStr := fmt.Sprintf("<span foreground=\"%s\">⍋</span>", c.NetIf.UpColor)
|
||||||
operstate = []byte(StatusStr)
|
operstate = []byte(statusStr)
|
||||||
case "down":
|
case "down":
|
||||||
statusStr := fmt.Sprintf("<span foreground=\"%s\">⍒</span>", c.NetIf.DownColor)
|
statusStr := fmt.Sprintf("<span foreground=\"%s\">⍒</span>", c.NetIf.DownColor)
|
||||||
operstate = []byte(statusStr)
|
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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/shirou/gopsutil/load"
|
"github.com/shirou/gopsutil/load"
|
||||||
@@ -22,7 +23,13 @@ func (c *MyConfig) UpdateLaStats() {
|
|||||||
ticker.Reset(Delay)
|
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)
|
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
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.Mem.ShowSwap {
|
||||||
sw, err := mem.SwapMemory()
|
sw, err := mem.SwapMemory()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -47,11 +48,10 @@ func (c *MyConfig) UpdateMemStats() {
|
|||||||
continue
|
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 != sw.Used/1024/1024 {
|
||||||
if c.Values.Memory.Usedpct != uint64(v.UsedPercent) || c.Values.Memory.Shared != v.Shared/1024/1024 || c.Values.Memory.Swap != v.SwapTotal-v.SwapFree {
|
|
||||||
c.Values.Memory.Usedpct = uint64(v.UsedPercent)
|
c.Values.Memory.Usedpct = uint64(v.UsedPercent)
|
||||||
c.Values.Memory.Shared = v.Shared / 1024 / 1024
|
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
|
c.Channels.UpdateReady <- true
|
||||||
}
|
}
|
||||||
} else {
|
} 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
|
var err error
|
||||||
|
|
||||||
// If we out of updates, seems someone killed pulseaudio server. Restart it.
|
// 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 {
|
if err := cmd.Run(); err == nil {
|
||||||
log.Printf("pulseaudio already running, but seems not responding, try gracefully kill it")
|
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 {
|
if err := cmd.Run(); err != nil {
|
||||||
return fmt.Errorf("unable to kill pulseaudio: %w", err)
|
return fmt.Errorf("unable to kill pulseaudio: %w", err)
|
||||||
@@ -127,7 +127,7 @@ func (c *MyConfig) PaReinit() error {
|
|||||||
cnt := 0
|
cnt := 0
|
||||||
|
|
||||||
for {
|
for {
|
||||||
cmd := exec.Command("pulseaudio", "--check")
|
cmd := exec.Command("pulseaudio", "--check") //nolint: noctx
|
||||||
|
|
||||||
// PA not running. Breakout of loop.
|
// PA not running. Breakout of loop.
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
@@ -154,10 +154,10 @@ func (c *MyConfig) PaReinit() error {
|
|||||||
// audio.
|
// audio.
|
||||||
if c.SimpleVolumePa.DontExitOnLogin {
|
if c.SimpleVolumePa.DontExitOnLogin {
|
||||||
// Do not exit on any kind of login/logout events.
|
// 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 {
|
} else {
|
||||||
// Exit immediately on logout(?).
|
// 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 {
|
if err := cmd.Run(); err != nil {
|
||||||
@@ -173,6 +173,8 @@ func (c *MyConfig) PaReinit() error {
|
|||||||
return err
|
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() {
|
func (c *MyConfig) SVPAHandler() {
|
||||||
for e := range c.Channels.SVPAHandlerChan {
|
for e := range c.Channels.SVPAHandlerChan {
|
||||||
if e.Button == 3 {
|
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"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
var PrintOutput = true
|
|
||||||
|
|
||||||
// SigHandler OS signal handler.
|
// SigHandler OS signal handler.
|
||||||
func (c *MyConfig) SigHandler() {
|
func (c *MyConfig) SigHandler() {
|
||||||
for s := range c.Channels.SigChan {
|
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
|
package lib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -11,8 +13,21 @@ import (
|
|||||||
// Spawner forks and execs given program, and also detaches form its control tty.
|
// Spawner forks and execs given program, and also detaches form its control tty.
|
||||||
func (c *MyConfig) Spawner() {
|
func (c *MyConfig) Spawner() {
|
||||||
for prg := range c.Channels.RunChan {
|
for prg := range c.Channels.RunChan {
|
||||||
devnullR, _ := os.Open(os.DevNull)
|
time.Sleep(25 * time.Millisecond)
|
||||||
devnullW, _ := os.OpenFile(os.DevNull, os.O_WRONLY|os.O_APPEND, 0644)
|
|
||||||
|
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{
|
spa := syscall.SysProcAttr{
|
||||||
Setsid: true,
|
Setsid: true,
|
||||||
@@ -30,6 +45,7 @@ func (c *MyConfig) Spawner() {
|
|||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Unable to spawn %s: %s", prg[0], err)
|
log.Printf("Unable to spawn %s: %s", prg[0], err)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = syscall.ForkExec(bin, prg, &pa)
|
_, err = syscall.ForkExec(bin, prg, &pa)
|
||||||
@@ -37,10 +53,6 @@ func (c *MyConfig) Spawner() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Unable to spawn %s: %s", prg[0], err)
|
log.Printf("Unable to spawn %s: %s", prg[0], err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close file errors we don't handle :) at all.
|
|
||||||
_ = devnullR.Close()
|
|
||||||
_ = devnullW.Close()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,8 +61,52 @@ func (c *MyConfig) CleanZombies() {
|
|||||||
r := syscall.Rusage{}
|
r := syscall.Rusage{}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
_, _ = syscall.Wait4(-1, nil, 0, &r)
|
pid, _ := syscall.Wait4(-1, nil, syscall.WNOHANG, &r)
|
||||||
|
|
||||||
|
if pid > 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
time.Sleep(1 * time.Minute)
|
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
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < len(buf); i++ {
|
buf = strings.TrimLeftFunc(buf, func(r rune) bool {
|
||||||
if strings.HasPrefix(buf, "{") {
|
return r != '{'
|
||||||
break
|
})
|
||||||
}
|
|
||||||
|
|
||||||
buf = buf[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(buf) == 0 {
|
|
||||||
log.Print("String from stdin has zero length, skipping")
|
|
||||||
|
|
||||||
|
if !strings.HasPrefix(buf, "{") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,18 +110,24 @@ func (c *MyConfig) ParseStdin() {
|
|||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
case app.Name != "" && e.Name == app.Name:
|
case app.Name != "" && e.Name == app.Name:
|
||||||
prg := append([]string{}, app.Cmd)
|
prg := append([]string{}, app.Cmd)
|
||||||
prg = append(prg, app.Args...)
|
prg = append(prg, app.Args...)
|
||||||
|
|
||||||
c.Channels.RunChan <- prg
|
c.Channels.RunChan <- prg
|
||||||
|
|
||||||
|
break
|
||||||
case app.Instance != "" && e.Instance == app.Instance:
|
case app.Instance != "" && e.Instance == app.Instance:
|
||||||
prg := append([]string{}, app.Cmd)
|
prg := append([]string{}, app.Cmd)
|
||||||
prg = append(prg, app.Args...)
|
prg = append(prg, app.Args...)
|
||||||
|
|
||||||
c.Channels.RunChan <- prg
|
c.Channels.RunChan <- prg
|
||||||
|
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -11,8 +12,8 @@ import (
|
|||||||
func (c *MyConfig) UpdateVPNStatus() {
|
func (c *MyConfig) UpdateVPNStatus() {
|
||||||
var (
|
var (
|
||||||
vpnCStatus string
|
vpnCStatus string
|
||||||
tcpCheck string
|
|
||||||
vpnCheck string
|
vpnCheck string
|
||||||
|
b strings.Builder
|
||||||
InitialDelay = 100 * time.Millisecond
|
InitialDelay = 100 * time.Millisecond
|
||||||
LoopIterationDelay = 3 * time.Second
|
LoopIterationDelay = 3 * time.Second
|
||||||
Delay = InitialDelay
|
Delay = InitialDelay
|
||||||
@@ -27,36 +28,47 @@ func (c *MyConfig) UpdateVPNStatus() {
|
|||||||
|
|
||||||
if c.VPNFileCheck() {
|
if c.VPNFileCheck() {
|
||||||
if c.Vpn.UpColor == "" {
|
if c.Vpn.UpColor == "" {
|
||||||
vpnCheck = `⍋`
|
b.WriteRune('⍋')
|
||||||
} else {
|
} else {
|
||||||
vpnCheck = fmt.Sprintf(`<span foreground="%s">⍋</span>`, c.Vpn.UpColor)
|
b.WriteString("<span foreground=\"")
|
||||||
|
b.WriteString(c.Vpn.UpColor)
|
||||||
|
b.WriteString("\">⍋</span>")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if c.Vpn.DownColor == "" {
|
if c.Vpn.DownColor == "" {
|
||||||
vpnCheck = `⍒`
|
b.WriteRune('⍒')
|
||||||
} else {
|
} 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.Vpn.TCPCheck.Enabled {
|
||||||
if c.VPNTCPCheck() {
|
if c.VPNTCPCheck() {
|
||||||
if c.Vpn.UpColor == "" {
|
if c.Vpn.UpColor == "" {
|
||||||
tcpCheck = `✔`
|
b.WriteRune('✔')
|
||||||
} else {
|
} else {
|
||||||
tcpCheck = fmt.Sprintf(`<span foreground="%s">✔</span>`, c.Vpn.UpColor)
|
b.WriteString("<span foreground=\"")
|
||||||
|
b.WriteString(c.Vpn.UpColor)
|
||||||
|
b.WriteString("\">✔</span>")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if c.Vpn.DownColor == "" {
|
if c.Vpn.DownColor == "" {
|
||||||
tcpCheck = `✘`
|
b.WriteRune('✘')
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
vpnCStatus = fmt.Sprintf("VPN:%s", vpnCheck)
|
vpnCStatus = "VPN:" + vpnCheck
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Values.VPNStatus != vpnCStatus {
|
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 {
|
func (c *MyConfig) VPNTCPCheck() bool {
|
||||||
conn, err := net.DialTimeout(
|
conn, err := net.DialTimeout( //nolint: noctx
|
||||||
"tcp",
|
"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),
|
time.Second*time.Duration(c.Vpn.TCPCheck.Timeout),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -100,3 +112,5 @@ func (c *MyConfig) VPNFileCheck() bool {
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|
||||||
|
|||||||
Reference in New Issue
Block a user