Skip to content
This repository has been archived by the owner on Dec 22, 2024. It is now read-only.

Commit

Permalink
Remove lazy_static and use sync::LazyLock
Browse files Browse the repository at this point in the history
Also put macro in an own file
  • Loading branch information
Ganneff committed Oct 20, 2024
1 parent e72b08d commit 10919d6
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 136 deletions.
15 changes: 7 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ clap-verbosity-flag = "^2"
directories = "^5.0"
fehler = "1.0.0"
itertools = "0.11"
lazy_static = "^1.5"
log = "^0.4"
quit = "^2.0"
rand = "^0.8"
Expand Down
71 changes: 71 additions & 0 deletions src/fromenvstatic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
////////////////////////////////////////////////////////////////////////
// Macros
////////////////////////////////////////////////////////////////////////
/// Help setting up static variables based on user environment.
///
/// We allow the user to configure certain properties/behaviours of tm
/// using environment variables. To reduce boilerplate in code, we use a
/// macro for setting them. We use [mod@`lazy_static`] to define them as
/// global variables, so they are available throughout the whole program -
/// they aren't going to change during runtime, ever, anyways.
///
/// # Examples
///
/// ```
/// # fn main() {
/// static ref TMPDIR: String = fromenvstatic!(asString "TMPDIR", "/tmp");
/// static ref TMSORT: bool = fromenvstatic!(asBool "TMSORT", true);
/// static ref TMWIN: u8 = fromenvstatic!(asU32 "TMWIN", 1);
/// # }
/// ```
macro_rules! fromenvstatic {
(asString $envvar:literal, $default:expr) => {
match env::var($envvar) {
Ok(val) => val,
Err(_) => $default.to_string(),
}
};
(asBool $envvar:literal, $default:literal) => {
match env::var($envvar) {
Ok(val) => match val.to_ascii_lowercase().as_str() {
"true" => true,
"false" => false,
&_ => {
// Test run as "cargo test -- --nocapture" will print this
if cfg!(test) {
println!(
"Variable {} expects true or false, not {}, assuming {}",
$envvar, val, $default
);
}
error!(
"Variable {} expects true or false, not {}, assuming {}",
$envvar, val, $default
);
return $default;
}
},
Err(_) => $default,
}
};
(asU32 $envvar:literal, $default:literal) => {
match env::var($envvar) {
Ok(val) => {
return val.parse::<u32>().unwrap_or_else(|err| {
if cfg!(test) {
println!(
"Couldn't parse variable {} (value: {}) as number (error: {}), assuming {}",
$envvar, val, err, $default
);
}
error!(
"Couldn't parse variable {} (value: {}) as number (error: {}), assuming {}",
$envvar, val, err, $default
);
$default
});
}
Err(_) => $default,
}
};
}
183 changes: 56 additions & 127 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@
#![warn(missing_docs)]

#[macro_use]
extern crate lazy_static;

mod config;
#[macro_use]
mod fromenvstatic;
mod session;

use crate::config::{Cli, Commands};
Expand All @@ -38,146 +37,76 @@ use std::{
io::{self, BufWriter, Write},
path::Path,
process::Command,
sync::LazyLock,
};
use tmux_interface::{ListSessions, NewSession, ShowOptions, Tmux};
use tracing::{debug, error, event, info, trace, warn, Level};
use tracing_subscriber::{fmt::time::ChronoLocal, FmtSubscriber};

////////////////////////////////////////////////////////////////////////
// Macros
////////////////////////////////////////////////////////////////////////
/// Help setting up static variables based on user environment.
///
/// We allow the user to configure certain properties/behaviours of tm
/// using environment variables. To reduce boilerplate in code, we use a
/// macro for setting them. We use [mod@`lazy_static`] to define them as
/// global variables, so they are available throughout the whole program -
/// they aren't going to change during runtime, ever, anyways.
///
/// # Examples
///
/// ```
/// # fn main() {
/// static ref TMPDIR: String = fromenvstatic!(asString "TMPDIR", "/tmp");
/// static ref TMSORT: bool = fromenvstatic!(asBool "TMSORT", true);
/// static ref TMWIN: u8 = fromenvstatic!(asU32 "TMWIN", 1);
/// # }
/// ```
macro_rules! fromenvstatic {
(asString $envvar:literal, $default:expr) => {
match env::var($envvar) {
Ok(val) => val,
Err(_) => $default.to_string(),
}
};
(asBool $envvar:literal, $default:literal) => {
match env::var($envvar) {
Ok(val) => match val.to_ascii_lowercase().as_str() {
"true" => true,
"false" => false,
&_ => {
// Test run as "cargo test -- --nocapture" will print this
if cfg!(test) {
println!(
"Variable {} expects true or false, not {}, assuming {}",
$envvar, val, $default
);
}
error!(
"Variable {} expects true or false, not {}, assuming {}",
$envvar, val, $default
);
return $default;
}
},
Err(_) => $default,
}
};
(asU32 $envvar:literal, $default:literal) => {
match env::var($envvar) {
Ok(val) => {
return val.parse::<u32>().unwrap_or_else(|err| {
if cfg!(test) {
println!(
"Couldn't parse variable {} (value: {}) as number (error: {}), assuming {}",
$envvar, val, err, $default
);
}
error!(
"Couldn't parse variable {} (value: {}) as number (error: {}), assuming {}",
$envvar, val, err, $default
);
$default
});
}
Err(_) => $default,
}
};
}

////////////////////////////////////////////////////////////////////////

// A bunch of "static" variables, though computed at program start, as they
// depend on the users environment.
lazy_static! {
/// We want a useful tmpdir, so set one if it isn't already. That's
/// the place where tmux puts its socket, so you want to ensure it
/// doesn't change under your feet - like for those with a
/// daily-changing tmpdir in their home...
static ref TMPDIR: String = fromenvstatic!(asString "TMPDIR", "/tmp");

/// Do you want me to sort the arguments when opening an
/// ssh/multi-ssh session? The only use of the sorted list is for
/// the session name, to allow you to get the same session again no
/// matter how you order the hosts on commandline.
static ref TMSORT: bool = fromenvstatic!(asBool "TMSORT", true);

/// Want some extra options given to tmux? Define TMOPTS in your
/// environment. Note, this is only used in the final tmux call
/// where we actually attach to the session!
static ref TMOPTS: String = fromenvstatic!(asString "TMOPTS", "-2");

/// The following directory can hold session config for us, so you
/// can use it as a shortcut.
static ref TMDIR: OsString = if let Some(user_dirs) = UserDirs::new() {
Path::join(
user_dirs.home_dir(),
Path::new(".tmux.d"))
.into_os_string()
/// We want a useful tmpdir, so set one if it isn't already. That's
/// the place where tmux puts its socket, so you want to ensure it
/// doesn't change under your feet - like for those with a
/// daily-changing tmpdir in their home...
static TMPDIR: LazyLock<String> = LazyLock::new(|| fromenvstatic!(asString "TMPDIR", "/tmp"));

/// Do you want me to sort the arguments when opening an
/// ssh/multi-ssh session? The only use of the sorted list is for
/// the session name, to allow you to get the same session again no
/// matter how you order the hosts on commandline.
static TMSORT: LazyLock<bool> = LazyLock::new(|| fromenvstatic!(asBool "TMSORT", true));

/// Want some extra options given to tmux? Define TMOPTS in your
/// environment. Note, this is only used in the final tmux call
/// where we actually attach to the session!
static TMOPTS: LazyLock<String> = LazyLock::new(|| fromenvstatic!(asString "TMOPTS", "-2"));

/// The following directory can hold session config for us, so you
/// can use it as a shortcut.
static TMDIR: LazyLock<OsString> = LazyLock::new(|| {
if let Some(user_dirs) = UserDirs::new() {
Path::join(user_dirs.home_dir(), Path::new(".tmux.d")).into_os_string()
} else {
error!("No idea where your homedir is, using /tmp");
Path::new("/tmp").as_os_str().to_owned()
};
}
});

/// Prepend the hostname to autogenerated session names?
///
/// Example: Call `tm ms host1 host2`.
/// * TMSESSHOST=true -> session name is `HOSTNAME_host1_host2`
/// * TMSESSHOST=false -> session name is `host1_host2`
static ref TMSESSHOST: bool = fromenvstatic!(asBool "TMSESSHOST", false);

/// Allow to globally define a custom ssh command line.
static ref TMSSHCMD: String = fromenvstatic!(asString "TMSSHCMD", "ssh");

/// From where does tmux start numbering its windows. Old shell
/// script used a stupid way of config parsing or setting it via
/// environment var. We now just use show_options, and in the
/// unlikely case this fails, try parsing the old environment var
/// TMWIN, and if that doesn't exist (quite likely now), just use
/// 1.
// FIXME: This depends on a running tmux daemon. None running -> data fetching
// fails. Could fix to detect that and start one first, later killing that.
static ref TMWIN: u32 = match Tmux::with_command(ShowOptions::new()
.global()
.quiet()
.value()
.option("base-index"))
.output()
/// Prepend the hostname to autogenerated session names?
///
/// Example: Call `tm ms host1 host2`.
/// * TMSESSHOST=true -> session name is `HOSTNAME_host1_host2`
/// * TMSESSHOST=false -> session name is `host1_host2`
static TMSESSHOST: LazyLock<bool> = LazyLock::new(|| fromenvstatic!(asBool "TMSESSHOST", false));

/// Allow to globally define a custom ssh command line.
static TMSSHCMD: LazyLock<String> = LazyLock::new(|| fromenvstatic!(asString "TMSSHCMD", "ssh"));

/// From where does tmux start numbering its windows. Old shell
/// script used a stupid way of config parsing or setting it via
/// environment var. We now just use show_options, and in the
/// unlikely case this fails, try parsing the old environment var
/// TMWIN, and if that doesn't exist (quite likely now), just use
/// 1.
// FIXME: This depends on a running tmux daemon. None running -> data fetching
// fails. Could fix to detect that and start one first, later killing that.
static TMWIN: LazyLock<u32> = LazyLock::new(|| {
match Tmux::with_command(
ShowOptions::new()
.global()
.quiet()
.value()
.option("base-index"),
)
.output()
{
Ok(v) => v.to_string().trim().parse().unwrap_or(1),
Err(_) => fromenvstatic!(asU32 "TMWIN", 1),
};
}
}
});

/// Run ls
///
Expand Down

0 comments on commit 10919d6

Please sign in to comment.