Created
March 18, 2018 20:23
-
-
Save neoneye/883881b3202f6327a4ee9cfddaf4b244 to your computer and use it in GitHub Desktop.
Tweakable Values in swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"Example 0": 3.1459, | |
"Example 1": 2.7182, | |
"Example 2": 1, | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let value0 = _tv(100) | |
let value1 = _tv(200) | |
print("the values are: \(value0) \(value1)") | |
if _tv(1) > 0.5 { | |
print("if-case") | |
} else { | |
print("else-case") | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import SwiftyJSON | |
struct LineColumn { | |
let line: Int | |
let column: Int | |
} | |
extension String { | |
func lineColumn(characterIndex: Int) -> LineColumn? { | |
var newlineCount = 1, columnCount = 1 | |
for (index, char) in self.enumerated() { | |
if index == characterIndex { | |
return LineColumn(line: newlineCount, column: columnCount) | |
} | |
if char == Character("\n") { | |
newlineCount += 1 | |
columnCount = 1 | |
continue | |
} | |
columnCount += 1 | |
} | |
return nil | |
} | |
} | |
func fileModificationDate(url: URL) -> Date? { | |
do { | |
let attr = try FileManager.default.attributesOfItem(atPath: url.path) | |
return attr[FileAttributeKey.modificationDate] as? Date | |
} catch { | |
return nil | |
} | |
} | |
struct TVFileItem { | |
let line: Int | |
let column0: Int | |
let column1: Int | |
let key: String | |
} | |
class TVFile { | |
let url: URL | |
var items = [TVFileItem]() | |
init(url: URL) { | |
self.url = url | |
process() | |
} | |
private func process() { | |
// print("loading file: \(self.url)") | |
let fileContent = try! String(contentsOf: self.url, encoding: .utf8) | |
let filename = self.url.lastPathComponent.stringByReplacing(string: ".swift", withString: "") | |
let pattern = "\\b_tv[(]\\w{1,20}[)]" | |
let regex = try! NSRegularExpression(pattern: pattern, options: []) | |
let matches: [NSTextCheckingResult] = regex.matches(in: fileContent, options: [], range: NSRange(location: 0, length: fileContent.count)) | |
//print("count: \(matches.count)") | |
var items = [TVFileItem]() | |
for (index, match) in matches.enumerated() { | |
guard match.numberOfRanges >= 1 else { | |
print("Expected 1 or more matches") | |
continue | |
} | |
let r = match.range | |
guard let lineColumn: LineColumn = fileContent.lineColumn(characterIndex: r.lowerBound) else { | |
print("Found no linecolumn for \(r.lowerBound)") | |
continue | |
} | |
let length: Int = r.upperBound - r.lowerBound | |
let key = "\(filename) \(index)" | |
//print("append item with key: \(key) range: \(r) lineColumn: \(lineColumn)") | |
let item = TVFileItem( | |
line: lineColumn.line, | |
column0: lineColumn.column, | |
column1: lineColumn.column + length, | |
key: key | |
) | |
items.append(item) | |
} | |
self.items = items | |
} | |
func key(line: Int, column: Int) -> String? { | |
let itemOrNil: TVFileItem? = items.first { | |
line == $0.line && column >= $0.column0 && column <= $0.column1 | |
} | |
return itemOrNil?.key | |
} | |
} | |
class TVManager { | |
static let shared = TVManager() | |
let jsonUrl = URL(fileURLWithPath: "/Users/StephenHawking/Desktop/demo.json") | |
var files = [TVFile]() | |
func key(file: String, line: Int, column: Int) -> String? { | |
let url = URL(fileURLWithPath: file, isDirectory: false) | |
for f in files { | |
if f.url == url { | |
return f.key(line: line, column: column) | |
} | |
} | |
let tvf = TVFile(url: url) | |
files.append(tvf) | |
return tvf.key(line: line, column: column) | |
} | |
var json: JSON? | |
var jsonModificationDate: Date? | |
private func loadJsonFileIfNeeded() { | |
var needLoad = true | |
if let date = fileModificationDate(url: self.jsonUrl) { | |
if date == jsonModificationDate { | |
print("unchanged modification date: \(date)") | |
needLoad = false | |
return | |
} | |
print("changed modification date: \(date)") | |
self.jsonModificationDate = date | |
} | |
if needLoad { | |
loadJsonFile() | |
} | |
} | |
private func loadJsonFile() { | |
let jsonString: String = try! String(contentsOf: jsonUrl, encoding: .utf8) | |
let json: JSON = JSON.parse(string: jsonString) | |
guard json.dictionary != nil else { | |
print("Expected json file to have a dictionary as root") | |
return | |
} | |
self.json = json | |
} | |
func floatValue(for key: String) -> Float? { | |
loadJsonFileIfNeeded() | |
guard let json = self.json else { | |
print("Unable to load json file") | |
return nil | |
} | |
let value = json[key] | |
guard value.exists() else { | |
print("json dictionary does not contain the key: \(key)") | |
return nil | |
} | |
guard let floatValue = value.float else { | |
print("found no float/int value for key: \(key)") | |
return nil | |
} | |
print("found value: \(floatValue) for key: \(key)") | |
return floatValue | |
} | |
func floatValue(_ defaultValue: Float, file: String, line: Int, column: Int) -> Float { | |
// print("defaultValue: \(defaultValue) file: \(file) line: \(line) column: \(column)") | |
guard let key = self.key(file: file, line: line, column: column) else { | |
print("found no key. file: \(file) line: \(line) column: \(column) returning defaultValue: \(defaultValue)") | |
return defaultValue | |
} | |
guard let overrideValue = self.floatValue(for: key) else { | |
print("json file contains no value for key: '\(key)' returning defaultValue: \(defaultValue)") | |
return defaultValue | |
} | |
print("key: '\(key)' value: \(overrideValue)") | |
return overrideValue | |
} | |
} | |
@discardableResult | |
func _tv(_ value: Float, file: String = #file, line: Int = #line, column: Int = #column) -> Float { | |
return TVManager.shared.floatValue(value, file: file, line: line, column: column) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment