168 lines
5.3 KiB
Rust
168 lines
5.3 KiB
Rust
use clap::Parser;
|
|
|
|
use penrose::{
|
|
builtin::{
|
|
actions::{exit, log_current_state, modify_with, send_layout_message, spawn, key_handler},
|
|
layout::{
|
|
messages::{ExpandMain, IncMain, ShrinkMain},
|
|
transformers::{Gaps, ReserveTop},
|
|
MainAndStack, Monocle,
|
|
},
|
|
},
|
|
core::{
|
|
bindings::{parse_keybindings_with_xmodmap, KeyEventHandler},
|
|
layout::LayoutStack,
|
|
Config, WindowManager,
|
|
},
|
|
extensions::{hooks::add_ewmh_hooks, actions::focus_or_spawn},
|
|
extensions::actions::toggle_fullscreen,
|
|
map, stack,
|
|
x11rb::RustConn,
|
|
Result,
|
|
util
|
|
};
|
|
use penrose_ui::{bar::Position, core::TextStyle, status_bar};
|
|
use std::collections::HashMap;
|
|
use tracing_subscriber::{self, prelude::*};
|
|
|
|
const FONT: &str = "Iosevka Slab Light";
|
|
const FONT_SIZE: i32 = 20;
|
|
const BLACK: u32 = 0x282828ff;
|
|
const WHITE: u32 = 0x7dd3fcff;
|
|
const GREY: u32 = 0x94a3b8ff;
|
|
const BLUE: u32 = 0x0c4a6eff;
|
|
const FOCUSED_BORDER: u32 = 0xd97706ff;
|
|
const NORMAL_BORDER: u32 = 0x64748ff;
|
|
|
|
const MAX_MAIN: u32 = 1;
|
|
const RATIO: f32 = 0.6;
|
|
const RATIO_STEP: f32 = 0.05;
|
|
const OUTER_PX: u32 = 5;
|
|
const INNER_PX: u32 = 5;
|
|
|
|
const TERMINAL: &str = "alacritty";
|
|
const EDITOR: &str = "emacsclient -c -n";
|
|
const SUSPEND: &str = "systemctl suspend";
|
|
const LOCK: &str = "slock";
|
|
const SET_THEME: &str = "lupan-set-theme";
|
|
const DMENU_ARGS: &[&str] = &["-fn", "Iosevka Slab Light"];
|
|
|
|
fn raw_key_bindings() -> HashMap<String, Box<dyn KeyEventHandler<RustConn>>> {
|
|
let mut theme = "dark";
|
|
let mut raw_bindings = map! {
|
|
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-c" => modify_with(|cs| cs.kill_focused()),
|
|
"M-a" => modify_with(|cs| cs.toggle_tag()),
|
|
"M-f" => toggle_fullscreen(),
|
|
"M-Return" => modify_with(|cs| cs.swap_focus_and_head()),
|
|
"M-m" => modify_with(|cs| cs.focus_head()),
|
|
"M-bracketright" => modify_with(|cs| cs.next_screen()),
|
|
"M-bracketleft" => modify_with(|cs| cs.previous_screen()),
|
|
"M-grave" => modify_with(|cs| cs.next_layout()),
|
|
"M-S-grave" => modify_with(|cs| cs.previous_layout()),
|
|
"M-comma" => send_layout_message(|| IncMain(1)),
|
|
"M-period" => send_layout_message(|| IncMain(-1)),
|
|
"M-l" => send_layout_message(|| ExpandMain),
|
|
"M-h" => send_layout_message(|| ShrinkMain),
|
|
"M-p" => key_handler(move |_, _| util::spawn_with_args("dmenu_run", DMENU_ARGS)),
|
|
"M-S-p" => spawn("rofi -theme Arc-Dark -show combi"),
|
|
"M-S-e" => spawn(EDITOR),
|
|
"M-S-s" => log_current_state(),
|
|
"M-S-Return" => spawn(TERMINAL),
|
|
"C-M-f" => focus_or_spawn("firefox", "firefox"),
|
|
"C-M-l" => spawn(LOCK),
|
|
"C-M-s" => spawn(SUSPEND),
|
|
"C-M-t" => focus_or_spawn("thunderbird", "thunderbird"),
|
|
"M-S-q" => exit(),
|
|
|
|
// Switch theme
|
|
"M-S-F6" => key_handler(move |_, _| {
|
|
theme = if theme == "dark" { "light" } else { "dark" };
|
|
util::spawn(format!("{} {}", SET_THEME, theme))
|
|
}),
|
|
};
|
|
|
|
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.focus_tag(tag)),
|
|
),
|
|
(
|
|
format!("M-S-{tag}"),
|
|
modify_with(move |client_set| client_set.move_focused_to_tag(tag)),
|
|
),
|
|
(
|
|
format!("M-C-{tag}"),
|
|
modify_with(move |client_set| client_set.pull_tag_to_screen(tag)),
|
|
),
|
|
]);
|
|
}
|
|
|
|
raw_bindings
|
|
}
|
|
|
|
fn layouts(bar_height_px: u32) -> 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))
|
|
}
|
|
|
|
#[derive(Parser, Debug)]
|
|
#[clap(about, version, author)]
|
|
struct Args {
|
|
/// Font name
|
|
#[clap(short, long, default_value_t = FONT.to_string())]
|
|
font: String,
|
|
|
|
/// Font size
|
|
#[clap(short = 's', long, default_value_t = FONT_SIZE)]
|
|
font_size: i32,
|
|
}
|
|
|
|
fn main() -> Result<()> {
|
|
let args = Args::parse();
|
|
tracing_subscriber::fmt()
|
|
.with_env_filter("debug")
|
|
.finish()
|
|
.init();
|
|
let bar_height_px = 2 * args.font_size as u32;
|
|
|
|
let config = add_ewmh_hooks(Config {
|
|
default_layouts: layouts(bar_height_px),
|
|
normal_border: NORMAL_BORDER.into(),
|
|
focused_border: FOCUSED_BORDER.into(),
|
|
..Config::default()
|
|
});
|
|
|
|
let conn = RustConn::new()?;
|
|
let key_bindings = parse_keybindings_with_xmodmap(raw_key_bindings())?;
|
|
let style = TextStyle {
|
|
font: FONT.to_string(),
|
|
point_size: args.font_size,
|
|
fg: WHITE.into(),
|
|
bg: Some(BLACK.into()),
|
|
padding: (2.0, 2.0),
|
|
};
|
|
|
|
let bar = status_bar(bar_height_px, &style, BLUE, GREY, Position::Top).unwrap();
|
|
|
|
let wm = bar.add_to(WindowManager::new(
|
|
config,
|
|
key_bindings,
|
|
HashMap::new(),
|
|
conn,
|
|
)?);
|
|
|
|
wm.run()
|
|
}
|