diff --git a/AVRsack.xcodeproj/project.pbxproj b/AVRsack.xcodeproj/project.pbxproj index ccb755e..5713a97 100644 --- a/AVRsack.xcodeproj/project.pbxproj +++ b/AVRsack.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ 9501D8091A17025C0034C530 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9501D8081A17025C0034C530 /* Images.xcassets */; }; 9501D80C1A17025C0034C530 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9501D80A1A17025C0034C530 /* MainMenu.xib */; }; 9501D8181A17025C0034C530 /* AVRsackTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9501D8171A17025C0034C530 /* AVRsackTests.swift */; }; + 95468DDF1A228BE600668EE2 /* ASHardware.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95468DDE1A228BE600668EE2 /* ASHardware.swift */; }; 95468DE31A228E1300668EE2 /* Defaults.plist in Resources */ = {isa = PBXBuildFile; fileRef = 95468DE21A228E1300668EE2 /* Defaults.plist */; }; 95BF80EB1A185C9E0004A693 /* ASFileTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95BF80EA1A185C9E0004A693 /* ASFileTree.swift */; }; 95EA32621A17B90600F66EB0 /* ACEView.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 95EA325B1A17B8DA00F66EB0 /* ACEView.framework */; }; @@ -68,6 +69,7 @@ 9501D8111A17025C0034C530 /* AVRsackTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AVRsackTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 9501D8161A17025C0034C530 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 9501D8171A17025C0034C530 /* AVRsackTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AVRsackTests.swift; sourceTree = ""; }; + 95468DDE1A228BE600668EE2 /* ASHardware.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ASHardware.swift; sourceTree = ""; }; 95468DE21A228E1300668EE2 /* Defaults.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Defaults.plist; sourceTree = ""; }; 958D76811A17DA1C00917D96 /* AVRsack-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AVRsack-Bridging-Header.h"; sourceTree = ""; }; 95BF80EA1A185C9E0004A693 /* ASFileTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ASFileTree.swift; sourceTree = ""; }; @@ -122,6 +124,7 @@ 9501D8011A17025C0034C530 /* ASApplication.swift */, 9501D8031A17025C0034C530 /* ASProjDoc.swift */, 95BF80EA1A185C9E0004A693 /* ASFileTree.swift */, + 95468DDE1A228BE600668EE2 /* ASHardware.swift */, 95BF80EC1A185CD90004A693 /* Resources */, 9501D7FF1A17025C0034C530 /* Supporting Files */, 95EA32671A17BAA600F66EB0 /* Frameworks */, @@ -317,6 +320,7 @@ buildActionMask = 2147483647; files = ( 9501D8041A17025C0034C530 /* ASProjDoc.swift in Sources */, + 95468DDF1A228BE600668EE2 /* ASHardware.swift in Sources */, 9501D8021A17025C0034C530 /* ASApplication.swift in Sources */, 95BF80EB1A185C9E0004A693 /* ASFileTree.swift in Sources */, ); diff --git a/AVRsack/ASHardware.swift b/AVRsack/ASHardware.swift new file mode 100644 index 0000000..a72866d --- /dev/null +++ b/AVRsack/ASHardware.swift @@ -0,0 +1,92 @@ +// +// ASHardware.swift +// AVRsack +// +// Created by Matthias Neeracher on 11/23/14. +// Copyright © 2014 Aere Perennius. All rights reserved. +// + +import Foundation + +typealias ASPropertyEntry = [String: String] +typealias ASProperties = [String: ASPropertyEntry] + +private func subdirectories(path: NSString) -> [NSString] { + let fileManager = NSFileManager.defaultManager() + var subDirs = [NSString]() + var isDir : ObjCBool = false + if fileManager.fileExistsAtPath(path, isDirectory: &isDir) && isDir { + for item in fileManager.contentsOfDirectoryAtPath(path, error: nil) as [NSString] { + let subPath = path+"/"+item + if fileManager.fileExistsAtPath(subPath, isDirectory: &isDir) && isDir { + subDirs.append(subPath) + } + } + } + return subDirs +} + +let hardwareInstance = ASHardware() +class ASHardware { + class func instance() -> ASHardware { return hardwareInstance } + let directories = [NSString]() + let programmers = ASProperties() + let boards = ASProperties() + init() { + // + // Gather hardware directories + // + let userDefaults = NSUserDefaults.standardUserDefaults() + let fileManager = NSFileManager.defaultManager() + if let arduinoPath = userDefaults.stringForKey("Arduino") { + let arduinoHardwarePath = arduinoPath + "/Contents/Resources/Java/hardware" + directories += subdirectories(arduinoHardwarePath) + } + for sketchDir in userDefaults.objectForKey("Sketchbooks") as [NSString] { + let hardwarePath = sketchDir + "/hardware" + directories += subdirectories(hardwarePath) + } + let property = NSRegularExpression(pattern: "\\s*(\\w+)\\.(\\S+?)\\s*=\\s*(\\S.*\\S)\\s*", options: nil, error: nil) + // + // Gather board declarations + // + for dir in directories { + let boardsPath = dir+"/boards.txt" + if let boardsFile = NSString(contentsOfFile: boardsPath, usedEncoding: nil, error: nil) { + var seen = [String: Bool]() + for line in boardsFile.componentsSeparatedByString("\n") as [NSString] { + if let match = property?.firstMatchInString(line, options: .Anchored, range: NSMakeRange(0, line.length)) { + let board = line.substringWithRange(match.rangeAtIndex(1)) + let property = line.substringWithRange(match.rangeAtIndex(2)) + let value = line.substringWithRange(match.rangeAtIndex(3)) + if seen.updateValue(true, forKey: board) == nil { + boards[board] = ASPropertyEntry() + } + boards[board]![property] = value + } + } + } + } + // + // Gather programmer declarations + // + for dir in directories { + let programmersPath = dir+"/programmers.txt" + if let programmersFile = NSString(contentsOfFile: programmersPath, usedEncoding: nil, error: nil) { + var seen = [String: Bool]() + for line in programmersFile.componentsSeparatedByString("\n") as [NSString] { + if let match = property?.firstMatchInString(line, options: .Anchored, range: NSMakeRange(0, line.length)) { + let programmer = line.substringWithRange(match.rangeAtIndex(1)) + let property = line.substringWithRange(match.rangeAtIndex(2)) + let value = line.substringWithRange(match.rangeAtIndex(3)) + if seen.updateValue(true, forKey: programmer) == nil { + programmers[programmer] = ASPropertyEntry() + seen[programmer] = true + } + programmers[programmer]![property] = value + } + } + } + } + } +} \ No newline at end of file