Wednesday, June 16, 2021

Fixing the horrible Firefox 89 interface

In searching for a fix to the Firefox 89 Proton layout catastrophe, I found a very neat site which tries to summarize all the fixes that can be made in “userChrome.css” file, which can be found in about:profiles internal URL, and enabled with toolkit.legacyUserProfileCustomizations.stylesheets in about:config.

Unfortunately, it’s not possible to restore the menu icons, as of yet, but it’s still a relief from that disaster.

This is my hack for Linux:

/*** Tighten up drop-down/context/popup menu spacing ***/

menupopup > menuitem, menupopup > menu {
	padding-block: 4px !important;
}
:root {
	--arrowpanel-menuitem-padding: 4px 8px !important;
}

/*** Proton Tabs Tweaks ***/

/* Adjust tab corner shape, optionally remove space below tabs */

#tabbrowser-tabs {
	--user-tab-rounding: 0px;
}
@media (-moz-proton) {
	.tab-background {
		border-radius: var(--user-tab-rounding) var(--user-tab-rounding) 0px 0px !important;
		margin-block: 1px 0 !important;
	}
	#scrollbutton-up, #scrollbutton-down { /* 6/10/2021 */
		border-top-width: 1px !important;
		border-bottom-width: 0 !important;
	}
	/* Container color bar visibility */
	.tabbrowser-tab[usercontextid] > .tab-stack > .tab-background > .tab-context-line {
		margin: 0px max(calc(var(--user-tab-rounding) - 3px), 0px) !important;
	}
}

/* Inactive tabs: Separator line style */

@media (-moz-proton) {
	.tabbrowser-tab:not([selected=true]):not([multiselected=true]):not([beforeselected-visible="true"]) .tab-background {
		border-right: 1px solid rgba(0, 0, 0, .20) !important;
	}
	/* For dark backgrounds */
	[brighttext="true"] .tabbrowser-tab:not([selected=true]):not([multiselected=true]):not([beforeselected-visible="true"]) .tab-background {
		border-right: 1px solid var(--lwt-selected-tab-background-color, rgba(255, 255, 255, .20)) !important;
	}
	.tabbrowser-tab:not([selected=true]):not([multiselected=true]) .tab-background {
		border-radius: 0 !important;
	}
	/* Remove padding between tabs */
	.tabbrowser-tab {
		padding-left: 0 !important;
		padding-right: 0 !important;
	}
}

Wednesday, June 2, 2021

Go’s defer in Rust

One of my all-time favorite features of Go is the defer mechanism. It’s so incredibly simple, and so incredibly ingenious and useful. The fact the deferred statements are called during a panic unwind makes me want to use it in other languages, like Rust.

As for Rust, I’m aware of the scopeguard crate, but it seems to be an overkill to such a simple concept. Plus, it does some fishy workaround to make the FnOnce.

So I decided to write my own Rust version of the defer mechanism, which turns out to be a macro that hides the creation of an object. This object holds a FnOnce which runs when at the end of the scope via Drop trait:

/// Internal struct used by the `defer!` macro.
pub struct Defer<F: FnOnce()> {
	func: Option<F>,
}

impl<F: FnOnce()> Defer<F> {
	pub fn new(func: F) -> Self {
		Self { func: Some(func) }
	}
}

impl<F: FnOnce()> Drop for Defer<F> {
	fn drop(&mut self) {
		self.func.take().map(|f| f());
	}
}

/// Defers the execution of a block until the surrounding scope ends.
macro_rules! defer {
	( $($tt:tt)* ) => {
		let _deferred = crate::defer::Defer::new(|| { $($tt)* });
	};
}

Usage is straightforward:

#[macro_use] mod defer; // considering defer.rs at crate's root

fn main() {
	defer! { println!("hi"); }
}

Edit: I published the code above as a crate: defer-lite.