Wednesday, April 24, 2024

Goodbye Go

On this morning, I just completely wiped away the Go compiler from my computer after finishing the Rust rewritten of my very useful ID3v2 editor, then written in Go. Now I have no tools written in Go anymore.

I consider I spent way too much time banging my head against the wall writing Windigo, trying to write a decent API. Go is way too limited, its lack of expressiveness won’t allow you to write any decent API more complex than a simple CRUD. And Win32 is hard. Windigo reached a point where there was nothing else I could do to make the API better – it was so bad it actually pushed me back to C++, where all my uneasiness started.

Another upsetting fact I noticed is that Go programmers tend to be unexperienced people. Beginners with trivial questions. Very demotivating.

I think anyone talking to me at this point would label me a “Go hater”. And as such, I can no more invest my scarce time in it. I remember in the early Windigo days I was completely in love with Go, with its first lines being written in my then girlfriend’s laptop. Yes, I installed the compiler there, and I don’t remember if it’s still there.

I plan to leave Windigo repo, and all its open issues, abandoned for a while. Maybe someone forks it and keeps it going. In the future, I will archive it, and I hope I never have to write Go ever again.

And that’s a shame, because “Windigo” is one of the coolest project names I ever came up with.

Tuesday, February 27, 2024

Linux recursive file searching

Searching recursively all files with the given extension:

find . -name "*.orig"

Searching all files containing the given text (source):

grep -Rn . -e "palavra"

Huge life saver.

Monday, January 15, 2024

Zustand, devtools and immer wrapper, pt. 2

On further researching of my previous idea of creating a Zustand + Immer wrapper, I found a very interesting technique straight from Zustand docs, where all the methods are simply free functions declared outside the store, called no store actions. I was already using this to declare private store methods, but it never occurred me to use it for all methods.

Since it officially has no downsides, I applied this idea to append the actions directly to the hook itself, so we don’t need to import each free function. The problem is that the hook has a couple methods itself, plus the inherent ones to any function object. So the result is very polluted. So I decided to adopt a convention of prefixing every action with $.

But conventions are easy to break. So I implemented a reduce to prefix each method name with #. But then TypeScript could not infer the type anymore, so I had to dig and type it manually with key remapping, and finally I got this implementation:

import {create, StateCreator} from 'zustand';
import {devtools} from 'zustand/middleware';
import {immer} from 'zustand/middleware/immer';
	
export function createStore<T extends object, U extends object>(
	name: string,
	initialState: T,
	actions: StateCreator<
		T,
		[['zustand/devtools', never], ['zustand/immer', never]],
		[['zustand/immer', never], ['zustand/devtools', never]],
		U
	>,
) {
	const store = create(
		devtools(
			immer(() => initialState),
			{name: name, serialize: true},
		),
	);

	type WithPrefix<T> = {
		[K in keyof T as K extends string ? `$${K}` : never]: T[K];
	}
	const actionsOrig = actions(store.setState, store.getState, store);
	const actionsPrefixed = Object.entries(actionsOrig).reduce(
		(accum, [k, v]) => ({...accum, ['$' + k]: v}),
		{} as WithPrefix<typeof actionsOrig>,
	);

	return Object.assign(store, actionsPrefixed);
}

This creator allows us to call actions directly, without the hook. They’ll be automatically prefixed with $:

const useFoo = createStore('Foo', {
	name: '',
}, (set, get) => ({
	setName(name: string): void {
		set(state => {
			state.name = name;
		});
	},
}));
	
function App() {
	const name = useFoo(s => s.name);

	return <div>
		<span>{name}</span>
		<button onClick={() => useFoo.$setName('Joe')}</button>
			Change
		</button>
	</div>;
}

That $ prefix gives me bad Vue vibes. Let’s see if I can get along with it, because I was able to develop a DX which is exactly what I was looking for.

Tuesday, January 9, 2024

Increase taskbar button width in Linux Mint 21

For my working VM, after ditching the sluggish Ubuntu 22 for the crazy good Mint Cinnamon 21, one of the customizations I wanted to make was the maximum width of the taskbar buttons. They seemed to narrow, while a lot of room was available.

After a couple minutes of searching, I found a direction in the Mint forums. The proposed solution is for Mint 20 – for Mint 21, it has a minor difference.

Edit, as root, the following file:

/usr/share/cinnamon/applets/grouped-window-list@cinnamon.org/constants.js

The value we’re after is MAX_BUTTON_WIDTH, which I increased from 150 to 210.

What caught my attention, though, is how all the layout building stuff is JavaScript.

Saturday, January 6, 2024

Installing dependencies of deb packages

A deb package can be installed on Linux by running:

sudo dpkg -i Package.deb

However, the installation may fail because dependencies are missing. In such cases, I found a tip which appears to work very well. After the failed dpkg command, run:

sudo apt-get -f install

This a shorthand for --fix-broken, and installs the dependencies and completes the aborted dpkg installation. Like magic.