Skip to content

Instantly share code, notes, and snippets.

@cmkilger
cmkilger / preferred_localizations.js
Created April 13, 2022 20:32
Pick a preferred language from a set of languages based on a list of preferences
// Finds the best locale from available locales based on the user's preferences. Falls back on the default locale if none is found.
function preferredLocale(preferences, availableLocales, defaultLocale) {
// Parses the BCP 47 locale into a ISO-639-3 language, ISO-15924 script, and M.49 region.
function parseLocale(locale) {
// Map grandfathered language identifiers to ISO-639
const grandfatheredMap = {
'art-lojban': 'jbo', 'i-ami': 'ami', 'i-bnn': 'bnn', 'i-hak': 'hak', 'i-klingon': 'tlh', 'i-lux': 'lb', 'i-navajo': 'nv',
'i-pwn': 'pwn', 'i-tao': 'tao', 'i-tay': 'tay', 'i-tsu': 'tsu', 'no-bok': 'nb', 'no-nyn': 'nn', 'sgn-BE-FR': 'sfb',
'sgn-BE-NL': 'vgt', 'sgn-CH-DE': 'sgg', 'zh-guoyu': 'zh', 'zh-hakka': 'hak', 'zh-min-nan': 'nan', 'zh-xiang': 'hsn'
}
@cmkilger
cmkilger / convert2xcframework
Created February 16, 2021 18:44
Converts iOS/Simulator universal frameworks into xcframeworks
#!/bin/sh
# Assumes that the framework contains i382, x86_64, armv7, and arm64
for path in "$@"
do
framework=$(basename "$path")
# Make sure it's a framework'
if [ "${framework##*.}" != "framework" ]; then
@cmkilger
cmkilger / UTF16Parsing.md
Created August 24, 2018 17:39
Code samples to get a substring using a UTF-16 range

Substrings from UTF-16 ranges

All these code examples produce the following output.

5
😀

Swift

@cmkilger
cmkilger / Clusterer.swift
Created October 18, 2017 23:01
OPTICS algorithm in Swift
import Foundation
public protocol Distanceable {
associatedtype Distance: Comparable
func distance(_ other: Self) -> Distance
}
public class Clusterer {
private class Point<ValueType: Distanceable> {
let value: ValueType
@cmkilger
cmkilger / SQLite.h
Last active September 28, 2017 07:51
Objective-C SQLite wrapper
#import <Foundation/Foundation.h>
@interface SQLiteDatabase: NSObject
- (nullable instancetype)initWithPath:(nonnull NSString *)path;
- (void)executeQuery:(nonnull NSString *)query;
- (void)executeQuery:(nonnull NSString *)query callback:(void(^ _Nullable)(NSDictionary<NSString *, id> * _Nonnull, BOOL * _Nonnull))callback;
@end
@cmkilger
cmkilger / WordRegexGen.m
Last active July 19, 2017 20:23
Generates a regular expression to match against multiple strings.
#import <Foundation/Foundation.h>
typedef enum {
CaseInsensitive = 1 << 0,
DiacraticInsensitive = 1 << 1,
CanEarlyTerminate = 1 << 2,
} Options;
@interface NSString (Diacritics)
@cmkilger
cmkilger / EmojiDetection.php
Last active February 8, 2019 17:24
Detects if a string is made up of just emoji (and space).
<?php
function isEmojiOnly($subject) {
$pattern = "/^[\\s\n\r]*(?:(?:[\xc2\xa9\xc2\xae\xe2\x80\xbc\xe2\x81\x89\xe2\x84\xa2\xe2\x84\xb9\xe2\x86\x94-\xe2\x86\x99\xe2\x86\xa9-\xe2\x86\xaa\xe2\x8c\x9a-\xe2\x8c\x9b\xe2\x8c\xa8\xe2\x8f\x8f\xe2\x8f\xa9-\xe2\x8f\xb3\xe2\x8f\xb8-\xe2\x8f\xba\xe2\x93\x82\xe2\x96\xaa-\xe2\x96\xab\xe2\x96\xb6\xe2\x97\x80\xe2\x97\xbb-\xe2\x97\xbe\xe2\x98\x80-\xe2\x98\x84\xe2\x98\x8e\xe2\x98\x91\xe2\x98\x94-\xe2\x98\x95\xe2\x98\x98\xe2\x98\x9d\xe2\x98\xa0\xe2\x98\xa2-\xe2\x98\xa3\xe2\x98\xa6\xe2\x98\xaa\xe2\x98\xae-\xe2\x98\xaf\xe2\x98\xb8-\xe2\x98\xba\xe2\x99\x88-\xe2\x99\x93\xe2\x99\xa0\xe2\x99\xa3\xe2\x99\xa5-\xe2\x99\xa6\xe2\x99\xa8\xe2\x99\xbb\xe2\x99\xbf\xe2\x9a\x92-\xe2\x9a\x94\xe2\x9a\x96-\xe2\x9a\x97\xe2\x9a\x99\xe2\x9a\x9b-\xe2\x9a\x9c\xe2\x9a\xa0-\xe2\x9a\xa1\xe2\x9a\xaa-\xe2\x9a\xab\xe2\x9a\xb0-\xe2\x9a\xb1\xe2\x9a\xbd-\xe2\x9a\xbe\xe2\x9b\x84-\xe2\x9b\x85\xe2\x9b\x88\xe2\x9b\x8e-\xe2\x9b\x8f\xe2\x9b\x91\xe2\x9b\x93-\xe2\x9b\x94\xe2\x9b\xa9-\xe2\x9b\xaa\xe2\x9b\xb0-\xe2\x
@cmkilger
cmkilger / DateFormatter+LocalizedFormats.swift
Last active October 5, 2017 19:45
NSDateFormatter extension for localizing non-standard dateFormats.
import Foundation
/// Removes key/value pairs from the format dictionary where another pair covers it.
///
/// The format dictionary should have locale identifiers as the keys, where language, script and country codes are separated by underscores (_), and the date format as the value.
///
/// Example: Given the following dictionary: ["en": "MMM d", "en_US": "MMM d"], "en_US" is unnessary because "en" (the language without the country) has the same format.
///
/// - parameter formats: The format dictionary to be reduced.
/// - parameter defaultFormat: A format that can be removed from the dictionary because it is the default. Defaults to `nil`.
@cmkilger
cmkilger / EmojiDetector.java
Last active July 1, 2023 07:17
Detects if a string is made up of just emoji (and space).
import java.util.regex.*;
class EmojiDetector {
private static Pattern r = Pattern.compile("^[\\s\n\r]*(?:(?:[\u00a9\u00ae\u203c\u2049\u2122\u2139\u2194-\u2199\u21a9-\u21aa\u231a-\u231b\u2328\u23cf\u23e9-\u23f3\u23f8-\u23fa\u24c2\u25aa-\u25ab\u25b6\u25c0\u25fb-\u25fe\u2600-\u2604\u260e\u2611\u2614-\u2615\u2618\u261d\u2620\u2622-\u2623\u2626\u262a\u262e-\u262f\u2638-\u263a\u2648-\u2653\u2660\u2663\u2665-\u2666\u2668\u267b\u267f\u2692-\u2694\u2696-\u2697\u2699\u269b-\u269c\u26a0-\u26a1\u26aa-\u26ab\u26b0-\u26b1\u26bd-\u26be\u26c4-\u26c5\u26c8\u26ce-\u26cf\u26d1\u26d3-\u26d4\u26e9-\u26ea\u26f0-\u26f5\u26f7-\u26fa\u26fd\u2702\u2705\u2708-\u270d\u270f\u2712\u2714\u2716\u271d\u2721\u2728\u2733-\u2734\u2744\u2747\u274c\u274e\u2753-\u2755\u2757\u2763-\u2764\u2795-\u2797\u27a1\u27b0\u27bf\u2934-\u2935\u2b05-\u2b07\u2b1b-\u2b1c\u2b50\u2b55\u3030\u303d\u3297\u3299\ud83c\udc04\ud83c\udccf\ud83c\udd70-\ud83c\udd71\ud83c\udd7e-\ud83c\udd7f\ud83c\udd8e\ud83c\udd91-\ud83c\udd9a\ud83c\ude01-\ud83c\ude02\ud83c\ude1a\ud83c
@cmkilger
cmkilger / NSString+EmojiDetection.swift
Last active March 28, 2018 21:28
Detects if a string is made up of just emoji (and space).
import Foundation
extension String {
private static let regex = try! NSRegularExpression(pattern: "^[\\s\n\r]*(?:(?:[\u{a9}\u{ae}\u{203c}\u{2049}\u{2122}\u{2139}\u{2194}-\u{2199}\u{21a9}-\u{21aa}\u{231a}-\u{231b}\u{2328}\u{23cf}\u{23e9}-\u{23f3}\u{23f8}-\u{23fa}\u{24c2}\u{25aa}-\u{25ab}\u{25b6}\u{25c0}\u{25fb}-\u{25fe}\u{2600}-\u{2604}\u{260e}\u{2611}\u{2614}-\u{2615}\u{2618}\u{261d}\u{2620}\u{2622}-\u{2623}\u{2626}\u{262a}\u{262e}-\u{262f}\u{2638}-\u{263a}\u{2648}-\u{2653}\u{2660}\u{2663}\u{2665}-\u{2666}\u{2668}\u{267b}\u{267f}\u{2692}-\u{2694}\u{2696}-\u{2697}\u{2699}\u{269b}-\u{269c}\u{26a0}-\u{26a1}\u{26aa}-\u{26ab}\u{26b0}-\u{26b1}\u{26bd}-\u{26be}\u{26c4}-\u{26c5}\u{26c8}\u{26ce}-\u{26cf}\u{26d1}\u{26d3}-\u{26d4}\u{26e9}-\u{26ea}\u{26f0}-\u{26f5}\u{26f7}-\u{26fa}\u{26fd}\u{2702}\u{2705}\u{2708}-\u{270d}\u{270f}\u{2712}\u{2714}\u{2716}\u{271d}\u{2721}\u{2728}\u{2733}-\u{2734}\u{2744}\u{2747}\u{274c}\u{274e}\u{2753}-\u{2755}\u{2757}\u{2763}-\u{2764}\u{2795}-\u{2797}\u{27a1}\u{27b0}\u{27bf}\u{2934}-\u{2