Skip to content

Instantly share code, notes, and snippets.

@neoneye
Created March 18, 2018 20:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save neoneye/883881b3202f6327a4ee9cfddaf4b244 to your computer and use it in GitHub Desktop.
Save neoneye/883881b3202f6327a4ee9cfddaf4b244 to your computer and use it in GitHub Desktop.
Tweakable Values in swift
{
"Example 0": 3.1459,
"Example 1": 2.7182,
"Example 2": 1,
}
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")
}
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