Skip to content

Instantly share code, notes, and snippets.

View msewell's full-sized avatar

Michael Sewell msewell

View GitHub Profile
@msewell
msewell / script.sh
Created October 19, 2021 13:50
Template: Basic shell script with launch arguments
#!/bin/bash
# The "<name you would refer to this script as in conversation with your team members>" script
#
# This script does <thingA> and <thingB> by way of <thingC>.
# It is generally used for <purpose>.
#
# Usage example: script.sh --some-argument=true --some-other-argument=false
#
# # This shell script follows the conventions set by the Google shell styleguide: https://google.github.io/styleguide/shellguide.html
extension Sequence {
func sorted<T: Comparable>(by keyPath: KeyPath<Element, T>, _ areInIncreasingOrder: ((T, T) -> Bool) = (<)) -> [Element] {
return sorted { a, b in
return areInIncreasingOrder(a[keyPath: keyPath], b[keyPath: keyPath])
}
}
}
@msewell
msewell / Array+firstMatchingType.swift
Created March 31, 2021 07:56
First element in array matching type
extension Array {
func first<T>(_ matchingType: T.Type) -> T? {
first(where: { $0 is T }) as? T
}
}
@msewell
msewell / lint-as-xcode-behavior.sh
Created March 31, 2021 07:54
Running SwiftLint as an Xcode behavior
#!/bin/bash -l
exec > /tmp/lintbehaviorlog-$(date "+%s").txt
exec 2>&1
set -x # Call this command at the top of your script and every following command will be echoed. You can turn it off with set +x
set -e # abort the script when any command exits with non-zero status
OIFS="$IFS"
IFS=$'\n'
@msewell
msewell / invokeTest.swift
Last active February 17, 2021 14:42
Invoke an XCTest multiple times by overriding XCTestCase's `invokeTest()` function
// In any XCTestCase subclass:
override func invokeTest() {
let maxInvocations = 100
(1...maxInvocations).forEach {
print("Test invocation: #\($0)/\(maxInvocations)")
super.invokeTest()
}
}
// In Objective-C:
@msewell
msewell / AXNameFromColor.swift
Last active October 22, 2021 00:00
AXNameFromColor: String representation of a CGColor
import Accessibility
import UIKit
extension CGColor {
var rgba: String { String(format: "R: %1.3f, G: %2.3f, B: %3.3f, A: %4.3f", components![0], components![1], components![2], components![3]) }
}
let hues: ClosedRange<Int> = (0...359)
hues // with constant saturation, brightness, and alpha
@msewell
msewell / assertDumpEqual.swift
Last active June 24, 2020 07:57
AssertEquals via `dump(_:)`. Equate the unequatable!
import func XCTest.XCTAssertEqual
/// Writes the output of `dump(_:)` into a string and returns it.
func dumpToString(_ dumpee: Any) -> String {
var string = ""
dump(dumpee, to: &string)
return string
}
@msewell
msewell / run-git-client-after-successful-test-run.sh
Last active June 22, 2020 10:15
Xcode behavior: run git client after successful test run
#!/bin/bash
cd $(dirname $XcodeProjectPath) # Xcode will fill $XcodeProjectPath with your project's path when run this script from an Xcode behavior
swiftlint autocorrect --config ~/Developer/.swiftlint.yml # Replace the path to your .swiftlint.yml if necessary (or leave it out entirely)
git diff-index --quiet HEAD || /usr/local/bin/stree $pwd # `stree` opens SourceTree, but can be replaced with your git client of choice
@msewell
msewell / .swiftlint.yml
Created June 12, 2020 08:44
Generate all-inclusive .swiftlint.yml
whitelist_rules:
- anyobject_protocol
- array_init
- attributes
- block_based_kvo
- class_delegate_protocol
- closing_brace
- closure_body_length
- closure_end_indentation
- closure_parameter_position
@msewell
msewell / UIColor+String.swift
Last active June 23, 2020 13:52
Generate a color from a string (deterministically)
import UIKit
extension UIColor {
/// Generate a color from the given string deterministically.
///
/// Generated colors are *not* evenly distributed in the HSL color space, but you and/or your users also probably won't be able to tell.
convenience init(_ string: String, saturation: Double = 0.8, brightness: Double = 0.8) {
let seed = Double.pi // Can be any positive irrational number. Pi was chosen for flavor.
let hash = string
.compactMap { $0.unicodeScalars.first?.value.byteSwapped }