Skip to content

Commit

Permalink
Prepare for 2.0 release (#47)
Browse files Browse the repository at this point in the history
* delete example fig file

* move empty example.lua to testfiles

* fix $XDG_CONFIG_HOME handling

it already includes .config, so only add .config to $HOME

* update readme
  • Loading branch information
ntBre authored Jan 20, 2025
1 parent 84c16bf commit f119600
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 155 deletions.
80 changes: 73 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,75 @@
# rwm
rust window manager ported from [dwm](https://dwm.suckless.org/)

For now this is a line-for-line port of dwm 6.4 with tons of unsafe code. Now
that it's working in this state, I'll start moving toward a safe Rust version
where possible. Linked lists are pretty cool, though.
rwm was originally a line-for-line port of dwm 6.4 with tons of unsafe code.
There's now a little bit less unsafe code, with some parts moved to safe Rust,
but there are now some functional differences from dwm too:
* Lua-based config file
* Several dwm patches applied
* [systray](https://dwm.suckless.org/patches/systray/) for a system tray
* [swallow](https://dwm.suckless.org/patches/swallow/) for window swallowing
* [pertag](https://dwm.suckless.org/patches/pertag/) for per-tag layouts and other settings
* [scratchpad](https://dwm.suckless.org/patches/scratchpad/) for a persistent
but hidable scratch terminal
* [stacker](https://dwm.suckless.org/patches/stacker/) (partial) for moving
windows up and down the stack

## Configuration
The default config file for rwm is `$XDG_CONFIG_HOME/rwm/config.lua` or
`$HOME/.config/rwm/config.lua` if `XDG_CONFIG_HOME` is not set. As inspired by
[ghostty](https://ghostty.org/docs)'s "Zero configuration" approach, the
default, empty config provides the normal dwm bindings out of the box. A warning
will be emitted if no config file is found, but rwm will substitute the default
value and run like normal.

The default config options are specified in [src/config.lua](src/config.lua),
with the settings ultimately ready from the `rwm` table therein. To override
settings in your own config file, just set the corresponding options on the
`rwm` table. For example, to enable `resize_hints` and change your default font,
add this code to your own `config.lua` file:

``` lua
rwm.resize_hints = true
rwm.fonts = {"monospace:size=12"}
```

Everything in `src/config.lua` is in scope when your config is read, so you can
use the `key`, `button`, and `rule` constructor functions, and the `tagkeys`
function for generating the repetitive Mod+1, ..., Mod+9 bindings for
manipulating tags.

### Key bindings
The code below is from my personal config but arguably should be included in the
repo. It handles overwriting existing keys when conflicts occur in your custom
bindings. If you don't locate existing keys and overwrite them, rwm will run all
bindings associated with the key, not just the newest one.

``` lua
-- Look for key collisions and replace any conflicts instead of appending. If
-- you actually want multiple behaviors on the same key, just call
-- `table.insert` directly
function locate_key (o)
for i, k in ipairs(rwm.keys) do
if k.keysym == o.keysym and k.mod_ == o.mod_ then
return i
end
end
return false
end

for _, key in ipairs(keys) do
idx = locate_key(key)
if idx then
rwm.keys[idx] = key
else
table.insert(rwm.keys, key)
end
end
```

Just combine this with a custom `keys` table like the one defined in
`src/config.lua`. Of course, if you'd rather include a full key table, you can
simply override `rwm.keys` directly.

## Screenshot
As you can see, it looks just like dwm, with the addition of a simple bar from
Expand All @@ -25,9 +91,9 @@ make install
This defers to `cargo install` and thus will place the resulting binary in
`~/.cargo/bin` by default.

I've been building with a Rust 1.81.0 nightly compiler from 2024-06-11 and test
in CI with nightly, but I don't use any nightly features, so it will likely
build with a stable toolchain too.
I've most recently built rwm with a stable 1.82 compiler, but I also test in CI
on nightly, so anything after 1.82 should work well. At least 1.82 is required
because I use the new `&raw` syntax from that release.

You'll also need the X11, Xft, Xinerama, and fontconfig libraries installed on
your system where rustc can find them, but the `x11` and `fontconfig-sys` crates
Expand All @@ -46,7 +112,7 @@ done
```

Wrapping it with this loop allows smoother restarting, but you can also use the
simpler `exec rwm` if you prefer.
simpler `exec rwm` if you prefer.

You can optionally set the log level with the `RUST_LOG` environment variable. I
think I only used `log::trace!`, so you'll need `RUST_LOG=trace` if you need to
Expand Down
136 changes: 0 additions & 136 deletions example.fig

This file was deleted.

22 changes: 10 additions & 12 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{
error::Error,
ffi::{c_float, c_int, c_uint, CString},
fs::read_to_string,
path::Path,
path::{Path, PathBuf},
};

use env::{CLICKS, HANDLERS, KEYS, XKEYS};
Expand Down Expand Up @@ -171,18 +171,16 @@ impl Config {
/// Attempt to load a config file on first usage from `$XDG_CONFIG_HOME`,
/// then `$HOME`, before falling back to the default config.
pub fn load_home() -> Self {
let mut home = std::env::var("XDG_CONFIG_HOME");
if home.is_err() {
home = std::env::var("HOME");
}
if home.is_err() {
let base = if let Ok(xdg_home) = std::env::var("XDG_CONFIG_HOME") {
PathBuf::from(xdg_home)
} else if let Ok(home) = std::env::var("HOME") {
PathBuf::from(home).join(".config")
} else {
log::warn!("unable to determine config directory");
return Config::default();
}
let config_path = Path::new(&home.unwrap())
.join(".config")
.join("rwm")
.join("config.lua");
};

let config_path = base.join("rwm").join("config.lua");

Config::from_lua(config_path).unwrap_or_else(|e| {
log::error!("failed to read config file: {e:?}");
Expand All @@ -199,7 +197,7 @@ mod tests {

#[test]
fn from_lua() {
let got = Config::from_lua("example.lua").unwrap();
let got = Config::from_lua("testfiles/config.lua").unwrap();
assert_debug_snapshot!(got)
}
}
File renamed without changes.

0 comments on commit f119600

Please sign in to comment.