Skip to content

Instantly share code, notes, and snippets.

@gubser
gubser / Log.fs
Created May 5, 2020 05:54
Simple console logging in F# (incomplete)
module Turns.Log
open System
open System.Threading.Tasks
open NodaTime
module Logging =
type LogLevel =
| Debug
| Info
@gubser
gubser / SuaveSerilogAdapter.fs
Last active May 9, 2020 19:54
Suave 2.5 to Serilog 2.9 adapter. Note: currently only handles Message, no Gauge
type SuaveSerilogAdapter(logger: Serilog.ILogger) =
let parser = Serilog.Parsing.MessageTemplateParser()
let write (level: Suave.Logging.LogLevel) (messageFactory: Suave.Logging.LogLevel -> Suave.Logging.Message) =
let message = messageFactory level
let level =
match level with
| Suave.Logging.LogLevel.Debug -> Serilog.Events.LogEventLevel.Debug
| Suave.Logging.LogLevel.Verbose -> Serilog.Events.LogEventLevel.Verbose
| Suave.Logging.LogLevel.Info -> Serilog.Events.LogEventLevel.Information
@gubser
gubser / computeTextLength.ts
Last active October 23, 2020 08:43
Compute width of SVG text using DOM
export function computeTextLength(content: string, fontSize?: string) {
const svgns = "http://www.w3.org/2000/svg";
// create elements
const svg: SVGSVGElement = document.createElementNS(svgns, 'svg');
const text: SVGTextElement = document.createElementNS(svgns, 'text');
text.textContent = content;
if(fontSize) {
text.style.fontSize = fontSize;
}
// hook them into dom
@gubser
gubser / WrappedText.tsx
Created October 21, 2020 08:13
Create auto-wrapping text in SVG
import React from 'react';
import { isArray } from 'lodash';
export function wrapText(s: string|undefined, maxLength: number): string[] {
if(s === undefined) {
return [];
} else if(s.length < maxLength) {
return [s];
} else {
const lastSpaceIndex = s.lastIndexOf(' ', maxLength);
@gubser
gubser / MultiLineText.tsx
Created October 28, 2020 10:06
Given maximum pixel width, create SVG text elements that wrap text around syllables (greedy)
import React from 'react';
export interface MultiLineTextProps extends React.SVGProps<SVGTextElement> {
children: string[];
}
export function MultiLineText({ children, ...rest }: MultiLineTextProps) {
if(children.length === 0) {
return <></>;
} else {
@gubser
gubser / subject.h
Last active April 15, 2021 12:09
Simple observer pattern in modern C++ without pointers.
#ifndef UTIL_SUBJECT_H
#define UTIL_SUBJECT_H
#include <memory>
#include <forward_list>
#include <functional>
/**
* Simple observer pattern in modern C++ without pointers.
* Register functions with make_observer() and call notify() to call them.
// from https://github.com/Gautam-Arora24/resize-observer-hook/blob/master/src/index.js
type UseResizeObserverMode = 'borderBoxSize'|'contentBoxSize'|'contentRect';
export function useResizeObserver<T extends Element>(option: UseResizeObserverMode = 'contentRect')
: [React.MutableRefObject<T|null>, number|undefined, number|undefined] {
const ref = useRef<T|null>(null);
const [height, setHeight] = useState<number|undefined>();
const [width, setWidth] = useState<number|undefined>();
const handleResize: ResizeObserverCallback = useCallback(entries => {
@gubser
gubser / binarySearch.ts
Created December 14, 2022 17:15
Binary search with typings from https://stackoverflow.com/a/50612218
// from https://stackoverflow.com/a/50612218
export function binarySearch<X>(xs: X[], x: X) {
let start = 0;
let end = xs.length - 1;
while (start <= end) {
let mid = Math.floor((start + end) / 2);
if (xs[mid] === x) {
return mid;
@gubser
gubser / TruncateExceptionFormatter.cs
Created February 24, 2023 08:08
Serilog Expression that truncates exception stack trace to 10'000 chars
var formatter = new ExpressionTemplate("{ {@t, @m, @r, @l: if @l = 'Information' then undefined() else @l, @x: if Length(@x) > 10000 then Concat(Substring(@x, 0, 9997), '...') else @x, ..@p} }\n")
LoggerConfiguration().WriteTo.Console(formatter)