Skip to content

Instantly share code, notes, and snippets.

View nikoheikkila's full-sized avatar
:electron:
Nice to meet you!

Niko Heikkilä nikoheikkila

:electron:
Nice to meet you!
View GitHub Profile
@nikoheikkila
nikoheikkila / README.md
Last active March 8, 2025 14:01
Fish Shell function for sourcing standard .env files

envsource

⚠️ NOTE (20.5.2023): I don't really use this function at all anymore since there are now tools such as Taskfile, which reads the .env file for me sparing me the need to pollute my session with environment variables.


I've been using Fish shell for years which is great and all, but one thing that has got me frustrated is using it with .env files.

When attempting to run source .env in a project, I usually encounter this problem:

@nikoheikkila
nikoheikkila / handlebars.ts
Created January 21, 2025 18:02
TypeScript: Compiling Handlebars templates with custom data
import Handlebars from "handlebars";
import fs from "node:fs";
type Data = Record<string, unknown>;
type Template = (data: Data) => string;
export default class Templater {
private readonly template: Template;
public static using(templatePath: string): Templater {
@nikoheikkila
nikoheikkila / interplanetary.py
Last active January 14, 2025 17:23
Python: Calculate person's weight on different planets
import sys
Weights = dict[str, float]
def calculate_planetary_weight(weight_kg: float) -> Weights:
"""
Calculate a person's weight on different planets in the Solar System.
Input weight should be in kilograms.
Returns a dictionary with weights on each planet in kilograms.
@nikoheikkila
nikoheikkila / harvest.fish
Last active March 22, 2024 06:03
A quick way to record a new time entry using the official Harvest CLI package.
# A quick way to record a new time entry using the official Harvest CLI package.
# Usage: `hours duration [alias]`
# Create a new alias for a project/task mapping with `hrvst alias create` if needed.
function hours -d "Record new entry to Harvest" -a hours -a alias
__hrvst_auth
if test (count $argv) -eq 0
__total_hours
return 0
end
@nikoheikkila
nikoheikkila / it.fish
Created May 19, 2022 16:55
Fish Shell: Interactive runner for your Taskfile tasks
# Example: `it -v`, then press <ENTER> to pick a single task, or <TAB> to select multiple tasks and then <ENTER>
function it -d 'Run Taskfile tasks interactively'
task $argv (\
task --list \
| cut -d ' ' -f2 \
| tail -n +2 \
| sed 's/://' \
| sort \
| fzf -m --reverse --preview 'task --summary {}' \
@nikoheikkila
nikoheikkila / Taskile.yml
Last active May 29, 2023 08:15
Global Task definitions for handling routine tasks across my computers.
# USAGE
#
# 1. Install Taskfile from <https://taskfile.dev>
# 2. Save this file to $HOME/Taskfile.yml
# 3. Run `task -g <name of the task>`
version: '3'
vars:
EDITOR: nvim # Set this to your preferred text editor
@nikoheikkila
nikoheikkila / CardGame.ts
Last active March 10, 2023 09:57
TypeScript version of the card game presented in the talk Domain Modelling Made Functional by Scott Wlaschin.
export enum Suit {
Club,
Diamond,
Spade,
Heart,
}
export enum Rank {
Two = 2,
Three,
@nikoheikkila
nikoheikkila / patcher.ts
Created March 1, 2023 17:14
Update TypeScript objects given a string path and a value.
const separator = ".";
const updateRecursively = <T extends Record<string, any>>(
data: T,
keys: string[],
value: unknown
): T => {
const [key] = keys;
if (keys.length === 1)
@nikoheikkila
nikoheikkila / fs-fake.ts
Last active February 28, 2023 06:57
In-Memory Filesystem Repository for Node.js & TypeScript
import * as fs from "node:fs/promises";
type Disk = Map<string, string>;
interface FileSystemAdapter {
readFile(path: string): Promise<string>;
writeFile(path: string, content: string): Promise<void>;
deleteFile(path: string): Promise<void>;
}
@nikoheikkila
nikoheikkila / directory_scanner.py
Last active October 22, 2022 08:16
General directory scanner implementation in pure Python
class PathScanner:
input_paths: list[str]
allowed_extensions: tuple[str]
def __init__(self, input_paths: list[str], allowed_extensions: tuple[str]) -> None:
self.input_paths = input_paths
self.allowed_extensions = allowed_extensions
def fetch_paths(self) -> list[str]:
result: list[str] = []