Skip to content

Instantly share code, notes, and snippets.

@sminez
Created October 31, 2022 14:07
Show Gist options
  • Save sminez/fba0f1ab12bce7ac56a0e60b81bd2306 to your computer and use it in GitHub Desktop.
Save sminez/fba0f1ab12bce7ac56a0e60b81bd2306 to your computer and use it in GitHub Desktop.
Example Penrose WM
use penrose::{
builtin::{
actions::{exit, log_current_state},
layout::{
messages::{ExpandMain, IncMain, ShrinkMain},
transformers::{Gaps, ReserveTop},
MainAndStack, Monocle,
},
},
core::{
actions::{modify_with, send_layout_message, spawn},
bindings::{parse_keybindings_with_xmodmap, KeyEventHandler},
layout::LayoutStack,
Config, WindowManager,
},
extensions::{
actions::dmenu_focus_client,
hooks::{
add_ewmh_hooks, add_named_scratchpads, manage::FloatingCentered, NamedScratchPad,
SpawnOnStartup, ToggleNamedScratchPad,
},
},
map, stack,
x::{query::ClassName, XConn},
x11rb::RustConn,
Color, Result,
};
use penrose_ui::{
bar::{
widgets::{ActiveWindowName, CurrentLayout, RootWindowName, Workspaces},
Position, StatusBar,
},
core::TextStyle,
};
use std::collections::HashMap;
use tracing_subscriber::{self, prelude::*};
const FONT: &str = "ProFontIIx Nerd Font";
const BLACK: u32 = 0x282828ff;
const WHITE: u32 = 0xebdbb2ff;
const GREY: u32 = 0x3c3836ff;
const BLUE: u32 = 0x458588ff;
const MAX_MAIN: u32 = 1;
const RATIO: f32 = 0.6;
const RATIO_STEP: f32 = 0.1;
const OUTER_PX: u32 = 5;
const INNER_PX: u32 = 5;
const BAR_HEIGHT_PX: u32 = 18;
const MAX_ACTIVE_WINDOW_CHARS: usize = 50;
fn raw_key_bindings(
toggle_scratch: ToggleNamedScratchPad,
) -> HashMap<String, Box<dyn KeyEventHandler<RustConn>>> {
let mut raw_bindings = map! {
// map_keys: |k: &str| format!("C-{k}");
map_keys: |k: &str| k.to_owned();
"M-j" => modify_with(|cs| cs.focus_down()),
"M-k" => modify_with(|cs| cs.focus_up()),
"M-S-j" => modify_with(|cs| cs.swap_down()),
"M-S-k" => modify_with(|cs| cs.swap_up()),
"M-S-q" => modify_with(|cs| cs.kill_focused()),
"M-S-c" => dmenu_focus_client(Default::default()),
"M-Tab" => modify_with(|cs| cs.toggle_tag()),
"M-bracketright" => modify_with(|cs| cs.next_screen()),
"M-bracketleft" => modify_with(|cs| cs.previous_screen()),
"M-S-bracketright" => modify_with(|cs| cs.drag_workspace_forward()),
"M-S-bracketleft" => modify_with(|cs| cs.drag_workspace_backward()),
"M-grave" => modify_with(|cs| cs.next_layout()),
"M-S-grave" => modify_with(|cs| cs.previous_layout()),
"M-Up" => send_layout_message(|| IncMain(1)),
"M-Down" => send_layout_message(|| IncMain(-1)),
"M-Right" => send_layout_message(|| ExpandMain),
"M-Left" => send_layout_message(|| ShrinkMain),
"M-semicolon" => spawn("rofi-apps"),
"M-S-s" => log_current_state(),
"M-Return" => spawn("st"),
"M-slash" => Box::new(toggle_scratch),
"M-A-l" => spawn("xflock4"),
"M-A-Escape" => exit(),
};
for tag in &["1", "2", "3", "4", "5", "6", "7", "8", "9"] {
raw_bindings.extend([
(
format!("M-{tag}"),
modify_with(move |client_set| client_set.pull_tag_to_screen(tag)),
),
(
format!("M-S-{tag}"),
modify_with(move |client_set| client_set.move_focused_to_tag(tag)),
),
]);
}
raw_bindings
}
fn layouts() -> LayoutStack {
stack!(
MainAndStack::side(MAX_MAIN, RATIO, RATIO_STEP),
MainAndStack::side_mirrored(MAX_MAIN, RATIO, RATIO_STEP),
MainAndStack::bottom(MAX_MAIN, RATIO, RATIO_STEP),
Monocle::boxed()
)
.map(|layout| ReserveTop::wrap(Gaps::wrap(layout, OUTER_PX, INNER_PX), BAR_HEIGHT_PX))
}
pub fn status_bar<X: XConn>(position: Position) -> penrose_ui::Result<StatusBar<X>> {
let highlight: Color = BLUE.into();
let empty_ws: Color = GREY.into();
let style = TextStyle {
font: FONT.to_string(),
point_size: 8,
fg: WHITE.into(),
bg: Some(BLACK.into()),
padding: (2.0, 2.0),
};
StatusBar::try_new(
position,
BAR_HEIGHT_PX,
style.bg.unwrap_or_else(|| 0x000000.into()),
&[&style.font],
vec![
Box::new(Workspaces::new(&style, highlight, empty_ws)),
Box::new(CurrentLayout::new(&style)),
// Box::new(penrose_bar::widgets::debug::StateSummary::new(style)),
Box::new(ActiveWindowName::new(
MAX_ACTIVE_WINDOW_CHARS,
&TextStyle {
bg: Some(highlight),
padding: (6.0, 4.0),
..style.clone()
},
true,
false,
)),
Box::new(RootWindowName::new(
&TextStyle {
padding: (4.0, 2.0),
..style.clone()
},
false,
true,
)),
],
)
}
fn main() -> Result<()> {
tracing_subscriber::fmt()
.with_env_filter("debug")
.finish()
.init();
// Run my init script on startup
let startup_hook = SpawnOnStartup::boxed("/usr/local/scripts/penrose-startup.sh");
// Float st-terminal windows spawned as fzf helpers from kakoune
let manage_hook = (ClassName("floatTerm"), FloatingCentered::new(0.8, 0.6));
let config = add_ewmh_hooks(Config {
default_layouts: layouts(),
manage_hook: Some(Box::new(manage_hook)),
startup_hook: Some(startup_hook),
..Config::default()
});
// Create a new named scratchpad and toggle handle for use in keybindings.
let (nsp, toggle_scratch) = NamedScratchPad::new(
"terminal",
"st -c StScratchpad",
ClassName("StScratchpad"),
FloatingCentered::new(0.8, 0.8),
true,
);
let conn = RustConn::new()?;
let key_bindings = parse_keybindings_with_xmodmap(raw_key_bindings(toggle_scratch))?;
// Initialise the required state extension and hooks for handling the named scratchpad
let wm = add_named_scratchpads(
WindowManager::new(config, key_bindings, HashMap::new(), conn)?,
vec![nsp],
);
let bar = status_bar(Position::Top).unwrap();
let wm = bar.add_to(wm);
wm.run()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment