├── src ├── weather │ ├── go.mod │ └── main.go ├── notifications-listener │ ├── go.mod │ ├── go.sum │ ├── notification.go │ └── main.go ├── workspaces │ ├── go.mod │ ├── go.sum │ └── main.go └── github │ ├── go.mod │ ├── main.go │ └── go.sum ├── .github ├── topbar.gif └── bottombar.gif ├── scripts ├── getram └── getvol ├── variables.yuck ├── controls.yuck ├── metrics.yuck ├── listeners.yuck ├── gruvbox.scss ├── pollers.yuck ├── readme.md ├── revealer.yuck ├── eww.scss └── eww.yuck /src/weather/go.mod: -------------------------------------------------------------------------------- 1 | module eww/weather 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /.github/topbar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/owenrumney/eww-bar/HEAD/.github/topbar.gif -------------------------------------------------------------------------------- /.github/bottombar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/owenrumney/eww-bar/HEAD/.github/bottombar.gif -------------------------------------------------------------------------------- /scripts/getram: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | printf "%.0f\n" $(free -m | grep Mem | awk '{print ($3/$2)*100}') 3 | -------------------------------------------------------------------------------- /scripts/getvol: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | amixer -D pulse sget Master | grep 'Left:' | awk -F'[][]' '{ print $2 }' | tr -d '%' | head -1 3 | -------------------------------------------------------------------------------- /src/notifications-listener/go.mod: -------------------------------------------------------------------------------- 1 | module eww/notification-listener 2 | 3 | go 1.16 4 | 5 | require github.com/godbus/dbus/v5 v5.0.6 // indirect 6 | -------------------------------------------------------------------------------- /variables.yuck: -------------------------------------------------------------------------------- 1 | (defvar revealSpotify false) 2 | (defvar revealDocker false) 3 | (defvar revealGithub false) 4 | (defvar revealVolume false) 5 | (defvar revealNotify false) -------------------------------------------------------------------------------- /src/notifications-listener/go.sum: -------------------------------------------------------------------------------- 1 | github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro= 2 | github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= 3 | -------------------------------------------------------------------------------- /src/workspaces/go.mod: -------------------------------------------------------------------------------- 1 | module eww/workspaces 2 | 3 | go 1.17 4 | 5 | require go.i3wm.org/i3/v4 v4.18.0 6 | 7 | require ( 8 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 // indirect 9 | github.com/BurntSushi/xgbutil v0.0.0-20160919175755-f7c97cef3b4e // indirect 10 | ) 11 | -------------------------------------------------------------------------------- /controls.yuck: -------------------------------------------------------------------------------- 1 | (defwidget termbutton [command ?text ?floating ?width ?height] 2 | (button :onclick "kitty -- sh -c '${floating == false ? "" : "i3-msg floating enable && clear && i3-msg resize set ${width == "" ? "800" : "${width}" }px ${height == "" ? "600" : "${height}" }px && i3-msg move position center && " } ${command}'" 3 | (label :text text) 4 | (children) 5 | ) 6 | ) -------------------------------------------------------------------------------- /src/notifications-listener/notification.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type Notification struct { 4 | AppName string 5 | ReplacesID uint32 6 | 7 | AppIcon string 8 | Summary string 9 | Body string 10 | } 11 | 12 | func decode(message []interface{}) (notification Notification) { 13 | 14 | return Notification{ 15 | AppIcon: message[0].(string), 16 | Summary: message[3].(string), 17 | Body: message[4].(string), 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /metrics.yuck: -------------------------------------------------------------------------------- 1 | (defwidget metric [icon value ?onchange ?onclick ?class ?height ?width] 2 | (box :orientation "h" 3 | :class "metric" 4 | :space-evenly false 5 | (termbutton :command "${onclick}" :height "1000" :width "1000" :text "${icon}") 6 | (scale :class {class != "" ? class : value > 50 ? value > 75 ? "error" : "warning" : "normal"} 7 | :min 0 8 | :max 101 9 | :active {onchange != ""} 10 | :value value 11 | :onchange onchange))) -------------------------------------------------------------------------------- /listeners.yuck: -------------------------------------------------------------------------------- 1 | (deflisten music 2 | :initial "" 3 | :onchange "eww update revealSpotify=true && sleep 5 && eww update revealSpotify=false" 4 | "playerctl --follow metadata --format '{{ artist }} - {{ title }}' || true") 5 | 6 | (deflisten musicStatus "playerctl --follow status || true") 7 | 8 | (deflisten workspace "workspaces 0") 9 | 10 | (deflisten notifications 11 | :initial "" 12 | :onchange "eww update revealNotify=true && sleep 5 && eww update revealNotify=false" 13 | "notification-listener") -------------------------------------------------------------------------------- /src/github/go.mod: -------------------------------------------------------------------------------- 1 | module eww/github 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/google/go-github/v39 v39.2.0 7 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be 8 | ) 9 | 10 | require ( 11 | github.com/golang/protobuf v1.3.2 // indirect 12 | github.com/google/go-querystring v1.1.0 // indirect 13 | golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect 14 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect 15 | google.golang.org/appengine v1.6.7 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /gruvbox.scss: -------------------------------------------------------------------------------- 1 | $background: #0d1117; 2 | $foreground: #b0b4bc; 3 | 4 | $background-alt: #232320; 5 | 6 | $black: #000; 7 | $white: #fff; 8 | 9 | $green: #98971a; 10 | $lightgreen: #b8bb26; 11 | $yellow: #d79921; 12 | $lightyellow: #fabd2d; 13 | $red: #cc241d; 14 | $lightred: #fb4934; 15 | $blue: #0db7ed; 16 | $lightblue: #83a598; 17 | $magenta: #b16286; 18 | $lightmagenta: #d3869b; 19 | $cyan: #689d6a; 20 | $lightcyan: #8ec07c; 21 | $gray: #928374; 22 | $lightgray: #a89984; 23 | 24 | $warning: $yellow; 25 | $error: $red; 26 | 27 | $urgent: $red; 28 | -------------------------------------------------------------------------------- /pollers.yuck: -------------------------------------------------------------------------------- 1 | (defpoll weather :interval "60s" "weather Northampton,UK") 2 | 3 | (defpoll volume :interval "1s" "scripts/getvol") 4 | 5 | (defpoll time :interval "10s" "date '+%H:%M'") 6 | 7 | (defpoll date :interval "10s" "date '+%b %d, %Y'") 8 | 9 | (defpoll wirelessId :interval "60s" "iwgetid -r") 10 | 11 | (defpoll interfaceId :interval "60s" "route | grep default | head -n1 | awk '{print $8}'") 12 | 13 | (defpoll dockerContainers :interval "10s" "docker ps -q | wc -l") 14 | 15 | (defpoll dockerImages :interval "10s" "docker images -q | wc -l") 16 | 17 | (defpoll githubInfo :interval "90m" "github-info aquasecurity:tfsec,aquasecurity:cfsec,owenrumney:go-sarif,owenrumney:squealer") -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | 2 | # Eww Config 3 | 4 | ## What is it 5 | 6 | Using [Eww Widgets](https://elkowar.github.io/eww/eww.html) to create a replacement for my `bumblebee-status` bars in `i3` Window Manager. 7 | 8 | Eww allows you to create widgets and style them up with css. It's extremely flexible. 9 | 10 | ## Screenshots 11 | 12 | ### Top Bar 13 | 14 | This is my top bar - workspaces are styled with icons from font-awesome and colour coded based on focus and urgency (red "Slack" workspace) 15 | 16 | Music details are coming from `playerctl` which is picking up my playing try from `ncspot` (Spotify CLI) 17 | 18 | ![Top bar](.github/topbar.gif) 19 | 20 | ### Bottom Bar 21 | 22 | Keeping it simple on the bottom bar - 23 | 24 | Workspaces repeated again on the left. On the right we have memory usage, CPU avg usage and disk usage. Then we have my primary interface throughput captured. 25 | 26 | ![Bottom bar](.github/bottombar.gif) 27 | 28 | -------------------------------------------------------------------------------- /src/notifications-listener/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/godbus/dbus/v5" 8 | ) 9 | 10 | func main() { 11 | conn, err := dbus.ConnectSessionBus() 12 | if err != nil { 13 | panic(err) 14 | } 15 | defer func() { 16 | _ = conn.Close() 17 | fmt.Println("Exiting....") 18 | }() 19 | 20 | call := conn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0, 21 | "eavesdrop='true',interface='org.freedesktop.Notifications',member='Notify'") 22 | if call.Err != nil { 23 | _, _ = fmt.Fprintln(os.Stderr, "Failed to add match:", call.Err) 24 | os.Exit(1) 25 | } 26 | 27 | c := make(chan *dbus.Message, 10) 28 | conn.Eavesdrop(c) 29 | for v := range c { 30 | notification := decode(v.Body) 31 | if notification.Body != "" { 32 | fmt.Printf("%s: %s\n", notification.Summary, notification.Body) 33 | } else { 34 | fmt.Printf("%s\n", notification.Summary) 35 | } 36 | 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/workspaces/go.sum: -------------------------------------------------------------------------------- 1 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc= 2 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 3 | github.com/BurntSushi/xgbutil v0.0.0-20160919175755-f7c97cef3b4e h1:4ZrkT/RzpnROylmoQL57iVUL57wGKTR5O6KpVnbm2tA= 4 | github.com/BurntSushi/xgbutil v0.0.0-20160919175755-f7c97cef3b4e/go.mod h1:uw9h2sd4WWHOPdJ13MQpwK5qYWKYDumDqxWWIknEQ+k= 5 | github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= 6 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 7 | go.i3wm.org/i3/v4 v4.18.0 h1:yV9SCpYeyTqEuele2bw7rLmEfrGCRlid9enTqLjPuG0= 8 | go.i3wm.org/i3/v4 v4.18.0/go.mod h1:FN6trxp2TXmfzQVa6JSKq5IJx/XUJsnPFKAz15cBWtw= 9 | golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc h1:ZMCWScCvS2fUVFw8LOpxyUUW5qiviqr4Dg5NdjLeiLU= 10 | golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 11 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= 12 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 13 | -------------------------------------------------------------------------------- /revealer.yuck: -------------------------------------------------------------------------------- 1 | (defwidget hovered-sign [var] 2 | (box :space-evenly false 3 | (revealer :reveal {!var} 4 | :duration "100ms" 5 | :transition "slideleft" 6 | (children :nth 0)) 7 | (revealer :reveal {var} 8 | :duration "100ms" 9 | :transition "slideleft" 10 | (children :nth 1)))) 11 | 12 | ; Revealer on hover, using children 13 | (defwidget revealer-on-hover [var varname ?class ?duration ?transition] 14 | (box :class "${class} revealer-on-hover" 15 | :orientation "h" 16 | :space-evenly false 17 | (eventbox :class "eventbox" 18 | :onhover "eww update ${varname}=true" 19 | :onhoverlost "eww update ${varname}=false" 20 | (box :space-evenly false 21 | (children :nth 0) 22 | (revealer :reveal var 23 | :transition {transition ?: "slideright"} 24 | :duration {duration ?: "500ms"} 25 | (children :nth 1)) 26 | (box :class "${class}" (children :nth 2)))))) 27 | 28 | 29 | (defwidget clickbox [var varname ?class ?duration ?transition] 30 | (box :class "${class} clickbox" :orientation "h" :space-evenly false 31 | (button :onclick "eww update ${varname}=${ var ? false : true }" 32 | (children :nth 0) 33 | ) 34 | (revealer :reveal var 35 | :transition {transition ?: "slideleft"} 36 | :duration {duration ?: "500ms"} 37 | (box :class "${class}" 38 | :space-evenly false 39 | (children :nth 1) 40 | (button :onclick "eww update ${varname}=false" :class "close" (label :text "Close")) 41 | ) 42 | ) 43 | ) 44 | ) -------------------------------------------------------------------------------- /src/github/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "net/http" 7 | "os" 8 | "strings" 9 | 10 | "github.com/google/go-github/v39/github" 11 | ) 12 | 13 | type gitInfo struct { 14 | org string 15 | stars int 16 | issues int 17 | pullRequests int 18 | } 19 | 20 | var githubIcon = "\uF09B" 21 | var starIcon = "\uF005" 22 | var issueIssue = "\uF192" 23 | 24 | func main() { 25 | 26 | gitDeets := make(map[string]gitInfo) 27 | 28 | ctx := context.Background() 29 | 30 | if len(os.Args) < 1 { 31 | panic("Usage: github-info org:repo,org:repo,org:repo") 32 | } 33 | 34 | checkers := strings.Split(os.Args[1], ",") 35 | client := github.NewClient(http.DefaultClient) 36 | 37 | for _, toCheck := range checkers { 38 | parts := strings.Split(toCheck, ":") 39 | if len(parts) != 2 { 40 | continue 41 | } 42 | 43 | org := parts[0] 44 | repo := parts[1] 45 | 46 | repositories, _, err := client.Search.Repositories(ctx, fmt.Sprintf("%s/%s", org, repo), nil) 47 | if err != nil { 48 | panic(err) 49 | } 50 | 51 | for _, repository := range repositories.Repositories { 52 | if repository.GetName() == repo { 53 | gitDeets[repo] = gitInfo{ 54 | org: org, 55 | stars: repository.GetStargazersCount(), 56 | issues: repository.GetOpenIssues(), 57 | } 58 | } 59 | } 60 | 61 | } 62 | 63 | fmt.Print(`(box :orientation "h" :space-evenly false`) 64 | for repo, info := range gitDeets { 65 | _ = repo 66 | _ = info 67 | fmt.Printf(`(button :onclick "eww update revealGithub=false && xdg-open https://github.com/%s/%s" (label :text " %s: %s %d %s %d | ")) `, info.org, repo, repo, starIcon, info.stars, issueIssue, info.issues) 68 | } 69 | fmt.Print(")") 70 | } 71 | -------------------------------------------------------------------------------- /src/workspaces/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // NICKED FROM https://github.com/liamg/dotfiles/blob/master/eww/src/workspaces/main.go 4 | 5 | import ( 6 | "fmt" 7 | "os" 8 | "strconv" 9 | "strings" 10 | 11 | "go.i3wm.org/i3/v4" 12 | ) 13 | 14 | func main() { 15 | 16 | if len(os.Args) <= 1 { 17 | panic("please supply output number") 18 | } 19 | 20 | index, err := strconv.Atoi(os.Args[1]) 21 | if err != nil { 22 | panic(err) 23 | } 24 | 25 | updateWorkspaces(index) 26 | 27 | subscription := i3.Subscribe(i3.WorkspaceEventType) 28 | for subscription.Next() { 29 | event := subscription.Event() 30 | switch event.(type) { 31 | case *i3.WorkspaceEvent: 32 | updateWorkspaces(index) 33 | } 34 | } 35 | } 36 | 37 | func updateWorkspaces(outputIndex int) { 38 | workspaces, err := i3.GetWorkspaces() 39 | if err != nil { 40 | fmt.Printf("Error: %s\n", err) 41 | return 42 | } 43 | 44 | var outputName string 45 | outputs, err := i3.GetOutputs() 46 | if err != nil { 47 | fmt.Printf("Error: %s\n", err) 48 | return 49 | } 50 | if outputIndex < len(outputs) { 51 | outputName = outputs[outputIndex].Name 52 | } 53 | 54 | // open box 55 | fmt.Printf(`(box :orientation "h" :space-evenly false :spacing 10`) 56 | for _, workspace := range workspaces { 57 | 58 | if workspace.Output != outputName { 59 | continue 60 | } 61 | 62 | var class string 63 | if workspace.Urgent { 64 | class = "urgent" 65 | } else if workspace.Focused { 66 | class = "focused" 67 | } 68 | 69 | fmt.Printf( 70 | `(button `+ 71 | `:onclick "i3-msg workspace '%s'"`+ 72 | `:class '%s'`+ 73 | `(label :text '%s'))`, 74 | workspace.Name, 75 | class, 76 | strings.TrimPrefix(workspace.Name, strconv.Itoa(int(workspace.Num))), 77 | ) 78 | } 79 | 80 | // close box + newline for send 81 | fmt.Println(")") 82 | } 83 | -------------------------------------------------------------------------------- /src/weather/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http" 7 | "os" 8 | "path/filepath" 9 | "strings" 10 | ) 11 | 12 | var icons = map[string]string{ 13 | "01d": "\uF185", // day clear 14 | "01n": "\uF186", // night clear 15 | "02d": "\uF0C2", // day few clouds 16 | "02n": "\uF0C2", // night few clouds 17 | "03d": "\uF0C2", // day scattered clouds 18 | "03n": "\uF0C2", // night scattered clouds 19 | "04d": "\uF0C2", // day broken clouds 20 | "04n": "\uF0C2", // night broken clouds 21 | "09d": "\uF0E9", // day showers 22 | "09n": "\uF73C", // night showers 23 | "10d": "\uF0E9", // day rain 24 | "10n": "\uF0E9", // night rain 25 | "11d": "\uF0E7", // day thunderstorm 26 | "11n": "\uF0E7", // night thunderstorm 27 | "13d": "\uF2DC", // day snow 28 | "13n": "\uF2DC", // night snow 29 | "50d": "\uF773", // day mist 30 | "50n": "\uF773", // night mist 31 | } 32 | 33 | type weather struct { 34 | Weather []struct { 35 | Main string `json:"main"` 36 | Description string `json:"description"` 37 | Icon string `json:"icon"` 38 | } `json:"weather"` 39 | Main struct { 40 | FeelsLike float32 `json:"feels_like"` 41 | } `json:"main"` 42 | } 43 | 44 | func main() { 45 | if len(os.Args) <= 1 { 46 | fmt.Println("Usage: weather [location]") 47 | os.Exit(1) 48 | } 49 | appId := getAppId() 50 | location := os.Args[1] 51 | degrees := '\u2103' 52 | weatherUrl := fmt.Sprintf("https://api.openweathermap.org/data/2.5/weather?units=Metric&appid=%s&q=%s", appId, location) 53 | resp, err := http.Get(weatherUrl) 54 | if err != nil || resp.StatusCode != http.StatusOK { 55 | panic(err) 56 | } 57 | defer func() { _ = resp.Body.Close() }() 58 | var w weather 59 | if err := json.NewDecoder(resp.Body).Decode(&w); err != nil { 60 | panic(err) 61 | } 62 | data, _ := json.Marshal(struct { 63 | Icon string `json:"icon"` 64 | Description string `json:"description"` 65 | }{ 66 | Icon: icons[w.Weather[0].Icon], 67 | Description: fmt.Sprintf("%s, %.0f%c ", strings.Title(w.Weather[0].Description), w.Main.FeelsLike, degrees), 68 | }) 69 | fmt.Printf("%s", string(data)) 70 | } 71 | func getAppId() string { 72 | homeDir, err := os.UserHomeDir() 73 | if err != nil { 74 | panic(err) 75 | } 76 | 77 | weatherFile := filepath.Join(homeDir, ".weatherkey") 78 | weatherKey, err := os.ReadFile(weatherFile) 79 | if err != nil { 80 | panic(fmt.Sprintf("Could not find weatherfile; %s", weatherFile)) 81 | } 82 | 83 | return strings.TrimSpace(string(weatherKey)) 84 | } 85 | -------------------------------------------------------------------------------- /src/github/go.sum: -------------------------------------------------------------------------------- 1 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 2 | github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= 3 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 4 | github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 5 | github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= 6 | github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 7 | github.com/google/go-github/v39 v39.2.0 h1:rNNM311XtPOz5rDdsJXAp2o8F67X9FnROXTvto3aSnQ= 8 | github.com/google/go-github/v39 v39.2.0/go.mod h1:C1s8C5aCC9L+JXIYpJM5GYytdX52vC1bLvHEF1IhBrE= 9 | github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= 10 | github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= 11 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 12 | golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= 13 | golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 14 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 15 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= 16 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 17 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= 18 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 19 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 20 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 21 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 22 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 23 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 24 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 25 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 26 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 27 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 28 | google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= 29 | google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 30 | -------------------------------------------------------------------------------- /eww.scss: -------------------------------------------------------------------------------- 1 | @import "gruvbox.scss"; 2 | 3 | * { 4 | all: unset; //Unsets everything so you can style everything from scratch 5 | } 6 | 7 | //Global Styles 8 | .bar { 9 | background-color: $background; 10 | color: $foreground; 11 | padding: 5px; 12 | font-size: 1em; 13 | font-family: Hack Regular; 14 | } 15 | 16 | .bottombar { 17 | background-color: $background; 18 | color: $foreground; 19 | padding: 5px; 20 | font-size: 1em; 21 | font-family: Hack Regular; 22 | } 23 | 24 | // Styles on classes (see eww.yuck for more information) 25 | 26 | .icon-module { 27 | margin: 0 5px; 28 | & > &__icon { 29 | margin-right: 5px; 30 | font-family: "Font Awesome 5 Free Solid"; 31 | } 32 | } 33 | 34 | .sidestuff slider { 35 | all: unset; 36 | color: #ffd5cd; 37 | } 38 | 39 | .metric scale trough highlight { 40 | all: unset; 41 | background-color: $green; 42 | color: $black; 43 | border-radius: 10px; 44 | } 45 | 46 | .metric scale.warning trough highlight { 47 | all: unset; 48 | background-color: $yellow; 49 | color: $black; 50 | border-radius: 10px; 51 | } 52 | 53 | .metric scale.error trough highlight { 54 | all: unset; 55 | background-color: $error; 56 | color: $black; 57 | border-radius: 10px; 58 | } 59 | 60 | .metric scale.volume trough highlight { 61 | all: unset; 62 | background-color: $lightmagenta; 63 | color: $black; 64 | border-radius: 10px; 65 | } 66 | 67 | .metric scale trough { 68 | all: unset; 69 | background-color: $background-alt; 70 | border-radius: 50px; 71 | min-height: 5px; 72 | min-width: 100px; 73 | margin-left: 10px; 74 | margin-right: 20px; 75 | } 76 | 77 | .label-ram { 78 | font-size: large; 79 | } 80 | 81 | .workspaces { 82 | background-color: $background-alt; 83 | border-radius: 15px; 84 | margin-left: 5px; 85 | margin-top: 5px; 86 | padding-left: 10px; 87 | padding-right: 5px; 88 | 89 | font-family: "Hack NF Regular"; 90 | font-size: 28px; 91 | margin-right: 20px; 92 | 93 | button { 94 | color: #a89984; 95 | margin: 0px 3px; 96 | } 97 | button.focused { 98 | color: $green; 99 | } 100 | button.urgent { 101 | color: $urgent; 102 | } 103 | } 104 | 105 | .spotify { 106 | font-size: 1em; 107 | // border-radius: 20px; 108 | background-color: $green; 109 | color: $background; 110 | } 111 | 112 | .spotify-text { 113 | font-size: 1em; 114 | background-color: $green; 115 | color: $green; 116 | } 117 | 118 | .notifications { 119 | font-size: 1em; 120 | // border-radius: 20px; 121 | background-color: red; 122 | color: $background; 123 | } 124 | 125 | .notifications-text { 126 | font-size: 1em; 127 | background-color: red; 128 | color: $green; 129 | } 130 | 131 | .docker { 132 | font-family: "Font Awesome 5 Brands"; 133 | // border-radius: 20px; 134 | font-size: 1em; 135 | background-color: $blue; 136 | color: $background; 137 | padding-left: 5px; 138 | padding-right: 5px; 139 | } 140 | 141 | .github { 142 | font-family: "Font Awesome 5 Brands"; 143 | font-size: 1em; 144 | background-color: $gray; 145 | color: $background; 146 | } 147 | 148 | .github-text { 149 | font-family: "Font Awesome 5 Brands"; 150 | font-size: 1em; 151 | background-color: $lightgray; 152 | color: $black; 153 | padding-top: 0.7em; 154 | } 155 | 156 | .volume { 157 | font-family: "Font Awesome 5 Brands"; 158 | font-size: 1em; 159 | border: 1px solid $gray; 160 | color: $foreground; 161 | } 162 | 163 | .uplink { 164 | color: $lightmagenta; 165 | } 166 | 167 | .veryuplink { 168 | color: $red; 169 | } 170 | 171 | .noactive { 172 | color: $white; 173 | } 174 | 175 | .downlink { 176 | color: $lightcyan; 177 | } 178 | 179 | .verydownlink { 180 | color: $green; 181 | } 182 | 183 | .close { 184 | background-color: $red; 185 | color: $background; 186 | padding-left: 5px; 187 | padding-right: 5px; 188 | } 189 | 190 | button:hover { 191 | text-decoration: underline; 192 | color: white; 193 | } 194 | -------------------------------------------------------------------------------- /eww.yuck: -------------------------------------------------------------------------------- 1 | ; Add the includes 2 | 3 | (include "variables.yuck") 4 | (include "controls.yuck") 5 | (include "listeners.yuck") 6 | (include "metrics.yuck") 7 | (include "pollers.yuck") 8 | (include "revealer.yuck") 9 | 10 | 11 | (defwidget bar [] 12 | (centerbox :orientation "h" 13 | (box :orientation "h" :space-evenly false (workspaces) ) 14 | (box :orientation "h" :space-evenly false (label :text " ${time} - ") (weather) ) 15 | (sidestuff) 16 | ) 17 | ) 18 | 19 | (defwidget bottombar [] 20 | (centerbox :orientation "h" 21 | (box :halign "start" :orientation "h" :space-evenly false (workspaces)) 22 | (box :halign "end" :orientation "h" :space-evenly false) 23 | (box :orientation "h" :halign "end" :space-evenly false 24 | (metric :icon "" 25 | :onclick "htop --sort-key PERCENT_MEM" 26 | :value {EWW_RAM.used_mem_perc}) 27 | (metric :icon "" 28 | :onclick "htop --sort-key PERCENT_CPU" 29 | :value {EWW_CPU.avg}) 30 | (metric :icon "" 31 | :onclick "mc" 32 | :value "${round(EWW_DISK["/"].used_perc, 0)}") 33 | (network) 34 | ) 35 | ) 36 | ) 37 | 38 | (defwidget workspaces [] 39 | (literal :class "workspaces" :content "${workspace}") 40 | ) 41 | 42 | (defwidget icon-module [icon ?class ?visible] 43 | (box :class "${class} icon-module" 44 | :orientation "h" 45 | :halign "start" 46 | :space-evenly false 47 | :visible {visible ?: true} ; because the argument is optional 48 | (label :class "icon-module__icon" :text "${icon}") 49 | (children) 50 | ) 51 | ) 52 | 53 | (defwidget sidestuff [] 54 | (box :class "sidestuff" :orientation "h" :space-evenly false :halign "end" :spacing 10 55 | (box :orientation "h" :spacing 2 :space-evenly false :halign "end" 56 | (volume) 57 | (spotify) 58 | (docker) 59 | (github) 60 | (notifications) 61 | ) 62 | ) 63 | ) 64 | 65 | (defwidget weather [] 66 | (icon-module :icon "${weather.icon}" 67 | (label :text "${weather.description}") 68 | ) 69 | ) 70 | 71 | (defwidget music [] 72 | (box :class "music" 73 | :orientation "h" 74 | :space-evenly false 75 | :halign "center" 76 | {music != "" ? "🎵${music}" : ""} 77 | ) 78 | ) 79 | 80 | 81 | (defwidget volume [?class] 82 | (box :space-evenly false 83 | :class "hover-module ${class}" 84 | (revealer-on-hover :class "hl-on-hover" 85 | :var revealVolume 86 | :varname "revealVolume" 87 | :transition "slideleft" 88 | :class "volume" 89 | 90 | (hovered-sign :var revealVolume 91 | (label :text "") 92 | (label :text "") 93 | ) 94 | (metric :icon "" 95 | :class "volume" 96 | :value volume 97 | :onchange "amixer -D pulse sset Master {}%") 98 | "  ") 99 | ) 100 | ) 101 | 102 | 103 | (defwidget notifications [?class] 104 | (box :space-evenly false 105 | :class "hover-module ${class}" 106 | (revealer-on-hover :class "hl-on-hover" 107 | :var revealNotify 108 | :varname "revealNotify" 109 | :transition "slideleft" 110 | :class "notifications" 111 | 112 | (hovered-sign :var revealNotify 113 | (label :class "notifications" :text "") 114 | (label :class "notifications" :text "") 115 | ) 116 | (button :onclick "playerctl play-pause" (label :class "notifications" :text " ${notifications} ")) 117 | "  ") 118 | ) 119 | ) 120 | 121 | (defwidget spotify [?class] 122 | (box :space-evenly false 123 | :class "hover-module ${class}" 124 | (revealer-on-hover :class "hl-on-hover" 125 | :var revealSpotify 126 | :varname "revealSpotify" 127 | :transition "slideleft" 128 | :class "spotify" 129 | 130 | (hovered-sign :var revealSpotify 131 | (label :class "spotify" :text "") 132 | (label :class "spotify" :text "") 133 | ) 134 | (button :onclick "playerctl play-pause" (label :class "spotify" :text " ${music} ")) 135 | "  - ${ musicStatus == "Playing" ? "" : "" } ") 136 | ) 137 | ) 138 | 139 | (defwidget docker [] 140 | (clickbox :var revealDocker :varname "revealDocker" :transition "slideleft" 141 | (label :class "docker" :text "  ${dockerContainers} " ) 142 | (box 143 | :class "docker" 144 | :space-evenly false 145 | :spacing 10 146 | 147 | (termbutton :command "eww update revealDocker=false && lazydocker" :class "ok" :width "1400" :text " Lazydocker" :floating true) 148 | ;(button :onclick "eww update revealDocker=false && docker system prune -f" :class "good" (label :text " Reclaim space") 149 | 150 | (button :onclick "eww update revealDocker=false && (docker ps -qa | xargs docker stop || true) " :class "warning" (label :text " Stop all containers") ) 151 | ) 152 | ) 153 | ) 154 | 155 | (defwidget github [] 156 | (clickbox :var revealGithub :varname "revealGithub" :transition "slideleft" 157 | (label :class "github" :text "  " ) 158 | (box 159 | :class "github" 160 | :space-evenly false 161 | :spacing 10 162 | (literal :class "github-text" :content "${githubInfo}") 163 | ) 164 | ) 165 | ) 166 | 167 | (defwidget network [] 168 | (box :orientation "h" :space-evenly false (label :text "${interfaceId}: ${round(EWW_NET[interfaceId].NET_UP / 1000000, 2)}") 169 | (label :class {round(EWW_NET[interfaceId].NET_UP / 1000000, 2) > 0.1 ? 170 | round(EWW_NET[interfaceId].NET_UP / 1000000, 2) > 5 ? 171 | "veryuplink" : "uplink" : "noactive"} :text "  " 172 | ) 173 | (label :text "${round(EWW_NET[interfaceId].NET_DOWN / 1000000, 2)}") 174 | (label :class {round(EWW_NET[interfaceId].NET_DOWN / 1000000, 2) > 0.1 ? 175 | round(EWW_NET[interfaceId].NET_DOWN / 1000000, 2) > 10 ? 176 | "verydownlink" : "downlink" : "noactive"} :text "  " 177 | ) 178 | ) 179 | ) 180 | ; 181 | 182 | (defwindow bar 183 | :monitor 0 184 | :windowtype "dock" 185 | :geometry (geometry :x "0%" 186 | :y "0%" 187 | :width "90%" 188 | :height "10px" 189 | :anchor "top center") 190 | :reserve (struts :side "top" :distance "4%") 191 | (bar) 192 | ) 193 | 194 | (defwindow bottombar 195 | :monitor 0 196 | :windowtype "dock" 197 | :geometry (geometry :x "0%" 198 | :y "0%" 199 | :width "90%" 200 | :height "10px" 201 | :anchor "bottom center") 202 | :reserve (struts :side "bottom" :distance "4%") 203 | (bottombar) 204 | ) 205 | 206 | --------------------------------------------------------------------------------