Skip to content

Instantly share code, notes, and snippets.

Avatar

Harry sonhanguyen

  • Melbourne, Australia
View GitHub Profile
View cv.htm
<head>
<style>
@media print { body { height: 297mm } }
body {
width: 210mm;
font-family: 'Courier New', Courier, monospace;
margin: 0;
display: flex;
}
@sonhanguyen
sonhanguyen / parser.ts
Last active Dec 24, 2020
Composable validation
View parser.ts
// I could not find any validation library (zod, io-ts etc) that allows custom error types
// so quickly wipped this up, note that the errors here are string literals but they
// might as well be, say, custom classes for pattern matching later
// think about error messages that you need to translate to many languages in the front-end
const formValidator = <S extends Record<string, Validator<any, any>>>(schema: S): Validator<
{ [K in keyof S]: Infer<S[K]>['Input'] },
{ [K in keyof S]:
{ error: Infer<S[K]>['Error']
value: Infer<S[K]>['Input']
@sonhanguyen
sonhanguyen / lens.ts
Last active Nov 30, 2020
typescript optics
View lens.ts
type Lens<State, Value> = {
(_: State): Value
set: (_: Value) => (_: State) => State
map<T>(_: Lens<Value, T>): Lens<State, T>
}
type Prop<K extends string, V = any> = Lens<Record<K, V>, V>
@sonhanguyen
sonhanguyen / cache.py
Last active Oct 17, 2020
A filesystem-based memoization decorator
View cache.py
import os
import collections
import pickle
import json
import urllib.parse
import re
from functools import wraps
from typing import Callable, Any
from dataclasses import dataclass, fields
View gist:4743d4b7c479d52c43a5447f831271ee
type NumericIndex = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
type Index<T extends any[]> = NumericIndex & keyof T
type UnionToIntersection<U> =
(U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never
type Builder<State = {}> = {
(): State
<A extends string[]>(...namedArgsOrder: A): <
V extends { [K in keyof A]: any },
T = UnionToIntersection<{ [K in Index<A>]: Record<string & A[K], V[K]> }[Index<A>]>
@sonhanguyen
sonhanguyen / overload.ts
Last active Sep 20, 2019
OverloadBuilder
View overload.ts
type Func = (..._) => any
const overload = <Default extends Func>(defaultFunc: Default): OverloadBuilder<Default> => {
// @ts-ignore
const match = cases => Object.assign(
(...args) => {
const matcher = cases.find(([ guard ]) => guard(args))
const func = matcher
? matcher[1]
: defaultFunc
@sonhanguyen
sonhanguyen / Default.bttpreset
Created Jul 20, 2019
Better touch tool setup for window management
View Default.bttpreset
{
"BTTPresetName" : "Default",
"BTTGeneralSettings" : {
"disableScrollingIf3" : true,
"BTTPasteWhenTriggeringClipboardAgain" : true,
"BTTForceNormalClickPressure5F" : 200,
"disableScrollingIf2" : true,
"BTTDidRegisterForUpdateStats" : "3.140",
"BTTShowControlStrip" : true,
"BTTShowControlStripItem" : true,
@sonhanguyen
sonhanguyen / app.tsx
Last active Sep 7, 2018
Services in React's new context API
View app.tsx
import * as React from 'react'
import { render } from 'react-dom'
import { compose, fromRenderProps } from 'recompose'
import { identity, pick, mapValues } from 'lodash'
const withDependencies = (...services: Array<[any, Function]>) => {
const enhance = compose(
...services.map(([service, mapProps]) => fromRenderProps(
Service.contextFor(service).Consumer,
mapProps
View Main.scala
import com.river11576.transcript_search._
import scala.concurrent.Await
import scala.concurrent.duration.Duration
object Main {
// https://www.wordhunt.xyz/api/freemium?phrase=test
def main(argv: Array[String]) = {
print(
Await.result(
View side panel style for using with Tree Tabs
/*#region Vivaldi */
#browser:not(.is-settingspage) > #header {
min-height: 0 !important;
height: 0;
}
#panels-container #panels > #switch {
-webkit-app-region: drag;
}