docs and renames
This commit is contained in:
59
src/main.rs
59
src/main.rs
@@ -5,30 +5,42 @@ use std::env;
|
||||
use std::process::Command;
|
||||
use std::{fs, str};
|
||||
|
||||
// parse the config to this
|
||||
/// Configuration for swayout.
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct Rules {
|
||||
struct Config {
|
||||
/// Monitor name is independent of output name. It can be anything.
|
||||
monitors: HashMap<String, Monitor>,
|
||||
// Map of layout name to : map of monitor name to output config
|
||||
/// Definition of layouts: a map of the layout name to the outputs.
|
||||
/// The outputs is a map of the monitor name (in `monitors`) to the configuration
|
||||
/// of that monitor for this layout.
|
||||
/// Available outputs that do not match a monitor in the map are disabled.
|
||||
layouts: HashMap<String, HashMap<String, OutputConfig>>,
|
||||
}
|
||||
/// Defines a monitor by make, model, and serial.
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct Monitor {
|
||||
make: String,
|
||||
model: String,
|
||||
serial: String,
|
||||
}
|
||||
/// Configuration for an enabled output.
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct OutputConfig {
|
||||
/// mode. See man 5 sway-output
|
||||
mode: String,
|
||||
/// scale. See man 5 sway-output
|
||||
scale: String,
|
||||
/// x value for position. See man 5 sway-output
|
||||
x: u16,
|
||||
/// y value for position. See man 5 sway-output
|
||||
y: u16,
|
||||
/// transform. See man 5 sway-output
|
||||
transform: String,
|
||||
}
|
||||
|
||||
// parse output of swaymsg -t get_outputs to this
|
||||
/// An output, as returned by `swaymsg -t get_outputs`.
|
||||
struct Output {
|
||||
/// output name, according to sway
|
||||
name: String,
|
||||
make: String,
|
||||
model: String,
|
||||
@@ -48,9 +60,8 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get all outputs currently available
|
||||
/// Get all outputs currently available, according to `swaymsg -t get_outputs`.
|
||||
fn get_outputs() -> Vec<Output> {
|
||||
// call `swaymsg -t get_outputs` to get outputs
|
||||
let output = Command::new("swaymsg")
|
||||
.arg("-t")
|
||||
.arg("get_outputs")
|
||||
@@ -82,7 +93,7 @@ fn get_outputs() -> Vec<Output> {
|
||||
}
|
||||
|
||||
/// Parse the mode from the output JSON into a string suitable for the mode param for sway-output.
|
||||
/// This will go into OutputConfig.mode
|
||||
/// This will go into `OutputConfig.mode`.
|
||||
fn get_mode(output: &Value) -> String {
|
||||
if let Value::Array(modes) = &output["modes"] {
|
||||
if let Some(mode) = modes.first() {
|
||||
@@ -101,15 +112,16 @@ fn get_mode(output: &Value) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the rules from ~/.config/swayout/config.toml
|
||||
fn get_rules() -> Rules {
|
||||
/// Get a `Config` from ~/.config/swayout/config.toml.
|
||||
/// (It really uses XDG config dirs.)
|
||||
fn get_config() -> Config {
|
||||
let xdg_dirs = xdg::BaseDirectories::with_prefix("swayout").unwrap();
|
||||
if let Some(path) = xdg_dirs.find_config_file("config.toml") {
|
||||
let toml = fs::read_to_string(path).expect("error reading file");
|
||||
toml::from_str(&toml).expect("toml parse error")
|
||||
} else {
|
||||
// no config files, use an empty rules
|
||||
Rules {
|
||||
Config {
|
||||
monitors: HashMap::new(),
|
||||
layouts: HashMap::new(),
|
||||
}
|
||||
@@ -118,17 +130,16 @@ fn get_rules() -> Rules {
|
||||
|
||||
/// Determine the available layout names.
|
||||
/// Return one layout for each layout defined in the configuration file
|
||||
/// (for which all outputs are available),
|
||||
/// one for each monitor defined in the configuration file
|
||||
/// (for using just that monitor),
|
||||
/// for which all outputs are available,
|
||||
/// one for each monitor defined in the configuration file (for using just that monitor),
|
||||
/// and one for each available output that is not a configured monitor (for using just that output).
|
||||
fn get_layouts() -> Vec<String> {
|
||||
let available_outputs = get_outputs();
|
||||
let rules = get_rules();
|
||||
let rules = get_config();
|
||||
|
||||
let mut layout_names: Vec<String> = Vec::new();
|
||||
|
||||
// Get the names of monitors that are available (that match a current output)
|
||||
// Get the names of monitors that are available (that match an available output)
|
||||
let available_monitor_names:Vec<&String> = rules.monitors.iter()
|
||||
.filter(|(_monitor_name,monitor)|
|
||||
available_outputs.iter().any(|output|
|
||||
@@ -175,9 +186,10 @@ fn print_layout_names() {
|
||||
}
|
||||
|
||||
/// Apply the specified layout.
|
||||
/// layout_name may be the name of a layout rule, the name of a monitor, or the name of an output.
|
||||
/// layout_name may be the name of a layout in the config, the name of a monitor,
|
||||
/// or the name of an output.
|
||||
fn apply_layout(layout_name: &String) {
|
||||
let rules = get_rules();
|
||||
let rules = get_config();
|
||||
let outputs = get_outputs();
|
||||
|
||||
// Map of output name to config for all outputs to enable.
|
||||
@@ -192,7 +204,6 @@ fn apply_layout(layout_name: &String) {
|
||||
let monitor = &rules.monitors[monitor_name];
|
||||
|
||||
// find the output for the monitor to get the output name.
|
||||
// (You can allegedly use "<make> <model> <serial>" instead of output name.)
|
||||
let output_opt = outputs.iter().find(|output| {
|
||||
output.make == monitor.make
|
||||
&& output.model == monitor.model
|
||||
@@ -210,8 +221,7 @@ fn apply_layout(layout_name: &String) {
|
||||
if let Some(monitor) = rules.monitors.get(layout_name) {
|
||||
// It is a monitor name. Find the matching output...
|
||||
if let Some(output) = outputs.iter().find(|output| {
|
||||
output.make == monitor.make
|
||||
&& output.model == monitor.model
|
||||
output.make == monitor.make && output.model == monitor.model
|
||||
&& output.serial == monitor.serial
|
||||
}) {
|
||||
output_config_map.insert(&output.name, &output.output_config);
|
||||
@@ -234,12 +244,13 @@ fn apply_layout(layout_name: &String) {
|
||||
|
||||
/// Apply the specified outputs. Enable all outputs in [outputs], disable others.
|
||||
fn apply_outputs(all_outputs: &Vec<Output>, outputs: &HashMap<&String, &OutputConfig>) {
|
||||
let mut cmd = Command::new("swaymsg");
|
||||
|
||||
// enabled first, then disabled.
|
||||
// That way if some work before an error, you at least have one output enabled.
|
||||
// set enabled outputs first, then set disabled outputs.
|
||||
// That way if some work before an error, you have at least one output enabled.
|
||||
|
||||
// for outputs to be enabled: map of output name to config
|
||||
let mut enabled: HashMap<&String,&OutputConfig> = HashMap::new();
|
||||
// for outputs to be disabled: output names
|
||||
let mut disabled: Vec<&String> = Vec::new();
|
||||
|
||||
all_outputs.iter().for_each(|output| {
|
||||
@@ -250,6 +261,7 @@ fn apply_outputs(all_outputs: &Vec<Output>, outputs: &HashMap<&String, &OutputCo
|
||||
}
|
||||
});
|
||||
|
||||
let mut cmd = Command::new("swaymsg");
|
||||
enabled.iter().for_each(|(output_name,output_config)| {
|
||||
cmd.arg("output");
|
||||
cmd.arg(&output_name);
|
||||
@@ -273,6 +285,7 @@ fn apply_outputs(all_outputs: &Vec<Output>, outputs: &HashMap<&String, &OutputCo
|
||||
cmd.arg(",");
|
||||
});
|
||||
|
||||
// print what we are about to do.
|
||||
cmd.get_args()
|
||||
.for_each(|arg| print!("{} ", arg.to_str().unwrap()));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user