Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@
*.out

# Vendor
vendor/
vendor/

btops
24 changes: 11 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,24 @@ bspwm desktop management that supports dymanic appending, removing, and renaming

## Introduction

Often times a workflow for a given day can't be defined by a set number of desktops with constant names. Btops enables you to define your workspaces based on what you're doing so you don't have worry about things like putting your applications in their respective desktops, running out of desktops, or leaving desktops unused and empty.
Often times a workflow for a given day can't be defined by a set number of desktops with constant names. Btops enables you to define your workspaces based on what you're doing so you don't have to worry about things like putting your applications in their respective desktops, running out of desktops, or leaving desktops unused and empty.

## Examples

#### Dynamic with classified renamers
[![btops dynamic](https://thumbs.gfycat.com/CourteousHeavyGibbon-size_restricted.gif)](https://gfycat.com/CourteousHeavyGibbon)

#### [Minmax](https://github.com/cmschuetz/btops/blob/master/examples/minmax.toml)
[![btops minmax](https://thumbs.gfycat.com/HairyRewardingIncatern-size_restricted.gif)](https://gfycat.com/HairyRewardingIncatern)

- [Dynamic with classified renamers](https://github.com/cmschuetz/btops/blob/master/examples/classified.toml)Add commentMore actions
- [Minmax with numeric renamer](https://github.com/cmschuetz/btops/blob/master/examples/minmax.toml)
- [Static](https://github.com/cmschuetz/btops/blob/master/examples/static.toml)

## Configuration

btops supports config files in toml, json, and yaml format. It'll look in the following places for config files:
btops supports config files in toml, json, and yaml format. It'll look in the following places for config files:

```
$XDG_CONFIG_HOME/btops/config.*
~/.config/btops/config.*
```

Below are the different configuration options available. Please look at [examples](https://github.com/cmschuetz/btops/tree/master/examples) for example usage
Below are the different configuration options available. Please look at [examples](https://github.com/cmschuetz/btops/tree/master/examples) for example usage

### Configuration Options

Expand All @@ -33,9 +30,10 @@ Below are the different configuration options available. Please look at [exampl
| min | Int | Minimum number of desktops per monitor | 1 |
| max | Int | Maximum number of desktops per monitor | infinity |
| remove-empty | Bool | Removes empty desktops | true |
| remove-focused | Bool | Removes focused desktops | false |
| append-when-occupied | Bool | Appends a new desktop when all other desktops are occupied | true |
| watch-config | Bool | Reload btops on next event when configuration changes | true |
| renamers | []String | Order of [renamers](#renamers) to use for renaming desktops. If a given renamer is unable to rename a desktop, it cascades to the next renmaer | ["numeric"]
| renamers | []String | Order of [renamers](#renamers) to use for renaming desktops. If a given renamer is unable to rename a desktop, it cascades to the next renmaer | ["numeric"] |
| names | Names | [Names configuration object](#names) | {} |

### Renamers
Expand All @@ -55,12 +53,12 @@ names configuration object
| ------ | ---- | ----------- |
| constant | String | A single string that the constant renamer uses to rename desktops |
| static | []String | A list of desktop names that the static renamer uses to rename desktops |
| classified | []{ classification: []String (clients) } | An array of objects that match client names with a given classification. If multiple classifications are matched, the first will be used as the desktop name
| classified | []{ classification: []String (clients) } | An array of objects that match client names with a given classification. If multiple classifications are matched, the first will be used as the desktop name |

## Installation

- Ensure [go](https://golang.org/) is installed and your [$GOPATH](https://github.com/golang/go/wiki/GOPATH) is set
- `go get github.com/cmschuetz/btops`
- Ensure [Go](https://go.dev/) is installed and your [$GOPATH](https://go.dev/wiki/GOPATH) is set
- `go install github.com/cmschuetz/btops@latest`
- run `$GOPATH/bin/btops`

### Arch Linux
Expand Down
2 changes: 2 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type Config struct {
Min int
Max int
RemoveEmpty bool `mapstructure:"remove-empty"`
RemoveFocused bool `mapstructure:"remove-focused"`
AppendWhenOccupied bool `mapstructure:"append-when-occupied"`
WatchConfig bool `mapstructure:"watch-config"`
configChangeC chan bool
Expand Down Expand Up @@ -89,6 +90,7 @@ func newDefaultConfig() *viper.Viper {
c.SetDefault("min", 1)
c.SetDefault("max", math.MaxInt64)
c.SetDefault("remove-empty", true)
c.SetDefault("remove-focused", true)
c.SetDefault("append-when-occupied", true)
c.SetDefault("renamers", []string{numeric})
c.SetDefault("watch-config", true)
Expand Down
26 changes: 26 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module github.com/cmschuetz/btops

go 1.21.6

require (
github.com/fsnotify/fsnotify v1.4.2
github.com/spf13/viper v1.0.0
)

require (
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/hashicorp/hcl v0.0.0-20171017181929-23c074d0eceb // indirect
github.com/magiconair/properties v1.7.3 // indirect
github.com/mitchellh/mapstructure v0.0.0-20171017171808-06020f85339e // indirect
github.com/pelletier/go-toml v1.0.1 // indirect
github.com/spf13/afero v1.0.0 // indirect
github.com/spf13/cast v1.1.0 // indirect
github.com/spf13/jwalterweatherman v0.0.0-20170901151539-12bd96e66386 // indirect
github.com/spf13/pflag v1.0.0 // indirect
github.com/stretchr/testify v1.8.4 // indirect
golang.org/x/sys v0.0.0-20171114162044-bf42f188b9bc // indirect
golang.org/x/text v0.1.1-0.20171102192421-88f656faf3f3 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v2 v2.0.0-20171116090243-287cf08546ab // indirect
)
43 changes: 43 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.4.2 h1:v5tKwtf2hNhBV24eNYfQ5UmvFOGlOCmRqk7/P1olxtk=
github.com/fsnotify/fsnotify v1.4.2/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/hashicorp/hcl v0.0.0-20171017181929-23c074d0eceb h1:1OvvPvZkn/yCQ3xBcM8y4020wdkMXPHLB4+NfoGWh4U=
github.com/hashicorp/hcl v0.0.0-20171017181929-23c074d0eceb/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/magiconair/properties v1.7.3 h1:6AOjgCKyZFMG/1yfReDPDz3CJZPxnYk7DGmj2HtyF24=
github.com/magiconair/properties v1.7.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mitchellh/mapstructure v0.0.0-20171017171808-06020f85339e h1:PtGHLB3CX3TFPcksODQMxncoeQKWwCgTg0bJ40VLJP4=
github.com/mitchellh/mapstructure v0.0.0-20171017171808-06020f85339e/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/pelletier/go-toml v1.0.1 h1:0nx4vKBl23+hEaCOV1mFhKS9vhhBtFYWC7rQY0vJAyE=
github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/spf13/afero v1.0.0 h1:Z005C09nPzwTTsDRJCQBVnpTU0bjTr/NhyWLj1nSPP4=
github.com/spf13/afero v1.0.0/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.1.0 h1:0Rhw4d6C8J9VPu6cjZLIhZ8+aAOHcDvGeKn+cq5Aq3k=
github.com/spf13/cast v1.1.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
github.com/spf13/jwalterweatherman v0.0.0-20170901151539-12bd96e66386 h1:zBoLErXXAvWnNsu+pWkRYl6Cx1KXmIfAVsIuYkPN6aY=
github.com/spf13/jwalterweatherman v0.0.0-20170901151539-12bd96e66386/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.0 h1:oaPbdDe/x0UncahuwiPxW1GYJyilRAdsPnq3e1yaPcI=
github.com/spf13/pflag v1.0.0/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.0.0 h1:RUA/ghS2i64rlnn4ydTfblY8Og8QzcPtCcHvgMn+w/I=
github.com/spf13/viper v1.0.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
golang.org/x/sys v0.0.0-20171114162044-bf42f188b9bc h1:pt5pMsz4A/sZRT17MOvX/nidmCt7n6ILLJBkNh5QqC8=
golang.org/x/sys v0.0.0-20171114162044-bf42f188b9bc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.1.1-0.20171102192421-88f656faf3f3 h1:OxMYHd6bm+jH+TI7NBCb/CaYk6pMJnBC8GIzIi68Hk4=
golang.org/x/text v0.1.1-0.20171102192421-88f656faf3f3/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v2 v2.0.0-20171116090243-287cf08546ab h1:yZ6iByf7GKeJ3gsd1Dr/xaj1DyJ//wxKX1Cdh8LhoAw=
gopkg.in/yaml.v2 v2.0.0-20171116090243-287cf08546ab/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
12 changes: 10 additions & 2 deletions handlers/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,20 @@ func (r RemoveHandler) ShouldHandle() bool {

func (r RemoveHandler) Handle(m *monitors.Monitors) bool {
for _, monitor := range *m {
if len(monitor.EmptyDesktops()) == 1 {
continue
}

for _, desktop := range monitor.EmptyDesktops() {
if *desktop == monitor.Desktops[len(monitor.Desktops)-1] {
if r.config.Min >= len(monitor.Desktops) {
continue
}

if r.config.Min >= len(monitor.Desktops) {
if !r.config.RemoveFocused && monitor.FocusedDesktopId == desktop.Id {
continue
}

if *desktop == monitor.Desktops[len(monitor.Desktops)-1] && !(monitor.Desktops[len(monitor.Desktops)-2].IsEmpty()) {
continue
}

Expand Down
1 change: 1 addition & 0 deletions monitors/monitors.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type bspwmState struct {
type Monitor struct {
Name string
Id int
FocusedDesktopId int
Desktops []Desktop
}

Expand Down