2014-11-24 01:02:29 +00:00
|
|
|
//
|
|
|
|
// ASHardware.swift
|
|
|
|
// AVRsack
|
|
|
|
//
|
|
|
|
// Created by Matthias Neeracher on 11/23/14.
|
|
|
|
// Copyright © 2014 Aere Perennius. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
import Foundation
|
|
|
|
|
2015-03-14 20:15:27 +00:00
|
|
|
typealias ASPropertyEntry = [String: String]
|
2014-11-24 01:02:29 +00:00
|
|
|
typealias ASProperties = [String: ASPropertyEntry]
|
|
|
|
|
2014-12-07 05:20:57 +00:00
|
|
|
extension NSMenu {
|
|
|
|
func addSortedChoices(choices:[ASPropertyEntry], target: AnyObject, selector: Selector) {
|
2015-11-16 01:56:33 +00:00
|
|
|
for choice in choices.sort({ $0["name"] < $1["name"] }) {
|
2014-12-08 04:35:58 +00:00
|
|
|
let item = self.addItemWithTitle(choice["name"]!, action: selector, keyEquivalent: "")
|
2014-12-07 05:20:57 +00:00
|
|
|
item?.target = target
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-14 16:43:20 +00:00
|
|
|
private func subdirectories(path: String) -> [String] {
|
2014-11-24 01:02:29 +00:00
|
|
|
let fileManager = NSFileManager.defaultManager()
|
2015-02-14 16:43:20 +00:00
|
|
|
var subDirs = [String]()
|
2014-11-24 01:02:29 +00:00
|
|
|
var isDir : ObjCBool = false
|
2015-11-16 01:56:33 +00:00
|
|
|
if let items = try? fileManager.contentsOfDirectoryAtPath(path) {
|
|
|
|
for item in items {
|
2014-11-24 01:02:29 +00:00
|
|
|
let subPath = path+"/"+item
|
|
|
|
if fileManager.fileExistsAtPath(subPath, isDirectory: &isDir) && isDir {
|
|
|
|
subDirs.append(subPath)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return subDirs
|
|
|
|
}
|
|
|
|
|
2014-11-28 13:18:53 +00:00
|
|
|
private let hardwareInstance = ASHardware()
|
2014-11-24 01:02:29 +00:00
|
|
|
class ASHardware {
|
|
|
|
class func instance() -> ASHardware { return hardwareInstance }
|
2015-02-14 16:43:20 +00:00
|
|
|
var directories = [String]()
|
|
|
|
var programmers = ASProperties()
|
|
|
|
var boards = ASProperties()
|
2014-11-24 01:02:29 +00:00
|
|
|
init() {
|
|
|
|
//
|
|
|
|
// Gather hardware directories
|
|
|
|
//
|
|
|
|
let userDefaults = NSUserDefaults.standardUserDefaults()
|
|
|
|
if let arduinoPath = userDefaults.stringForKey("Arduino") {
|
|
|
|
let arduinoHardwarePath = arduinoPath + "/Contents/Resources/Java/hardware"
|
|
|
|
directories += subdirectories(arduinoHardwarePath)
|
|
|
|
}
|
2015-02-14 16:43:20 +00:00
|
|
|
for sketchDir in userDefaults.objectForKey("Sketchbooks") as! [String] {
|
2014-11-24 01:02:29 +00:00
|
|
|
let hardwarePath = sketchDir + "/hardware"
|
|
|
|
directories += subdirectories(hardwarePath)
|
|
|
|
}
|
2015-11-16 01:56:33 +00:00
|
|
|
let property = try! NSRegularExpression(pattern: "\\s*(\\w+)\\.(\\S+?)\\s*=\\s*(\\S.*\\S)\\s*", options: [])
|
2014-11-24 01:02:29 +00:00
|
|
|
//
|
|
|
|
// Gather board declarations
|
|
|
|
//
|
|
|
|
for dir in directories {
|
2014-12-07 05:20:57 +00:00
|
|
|
let boardsPath = dir+"/boards.txt"
|
2015-11-16 01:56:33 +00:00
|
|
|
let provenience = (dir as NSString).lastPathComponent
|
|
|
|
if let boardsFile = try? NSString(contentsOfFile: boardsPath, usedEncoding: nil) {
|
2014-11-24 01:02:29 +00:00
|
|
|
var seen = [String: Bool]()
|
2015-11-16 01:56:33 +00:00
|
|
|
for line in boardsFile.componentsSeparatedByString("\n") {
|
|
|
|
if let match = property.firstMatchInString(line, options: .Anchored, range: NSMakeRange(0, line.utf16.count)) {
|
|
|
|
let nsline = line as NSString
|
|
|
|
let board = nsline.substringWithRange(match.rangeAtIndex(1)) as String
|
|
|
|
let property = nsline.substringWithRange(match.rangeAtIndex(2)) as String
|
|
|
|
let value = nsline.substringWithRange(match.rangeAtIndex(3)) as String
|
2014-11-24 01:02:29 +00:00
|
|
|
if seen.updateValue(true, forKey: board) == nil {
|
2014-12-07 05:20:57 +00:00
|
|
|
boards[board] = ASPropertyEntry()
|
|
|
|
boards[board]!["provenience"] = provenience
|
2015-01-07 09:30:28 +00:00
|
|
|
boards[board]!["library"] = dir
|
2014-11-24 01:02:29 +00:00
|
|
|
}
|
|
|
|
boards[board]![property] = value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-12-07 05:20:57 +00:00
|
|
|
|
2014-11-24 01:02:29 +00:00
|
|
|
//
|
|
|
|
// Gather programmer declarations
|
|
|
|
//
|
|
|
|
for dir in directories {
|
|
|
|
let programmersPath = dir+"/programmers.txt"
|
2015-11-16 01:56:33 +00:00
|
|
|
let provenience = (dir as NSString).lastPathComponent
|
|
|
|
if let programmersFile = try? NSString(contentsOfFile: programmersPath, usedEncoding: nil) {
|
2014-11-24 01:02:29 +00:00
|
|
|
var seen = [String: Bool]()
|
2015-11-16 01:56:33 +00:00
|
|
|
for line in programmersFile.componentsSeparatedByString("\n") {
|
|
|
|
if let match = property.firstMatchInString(line, options: .Anchored, range: NSMakeRange(0, line.utf16.count)) {
|
|
|
|
let nsline = line as NSString
|
|
|
|
let programmer = nsline.substringWithRange(match.rangeAtIndex(1))
|
|
|
|
let property = nsline.substringWithRange(match.rangeAtIndex(2))
|
|
|
|
let value = nsline.substringWithRange(match.rangeAtIndex(3))
|
2014-11-24 01:02:29 +00:00
|
|
|
if seen.updateValue(true, forKey: programmer) == nil {
|
|
|
|
programmers[programmer] = ASPropertyEntry()
|
2014-12-07 05:20:57 +00:00
|
|
|
programmers[programmer]!["provenience"] = provenience
|
2014-11-24 01:02:29 +00:00
|
|
|
}
|
|
|
|
programmers[programmer]![property] = value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-12-07 05:20:57 +00:00
|
|
|
|
|
|
|
func buildMenu(menu:NSMenu, choices:ASProperties, recentChoices:[String], target: AnyObject, selector: Selector) {
|
|
|
|
menu.removeAllItems()
|
2015-06-07 00:31:21 +00:00
|
|
|
menu.addItemWithTitle("Title", action: "", keyEquivalent: "")
|
2014-12-07 05:20:57 +00:00
|
|
|
if choices.count <= 10 {
|
|
|
|
menu.addSortedChoices([ASPropertyEntry](choices.values), target: target, selector: selector)
|
|
|
|
} else {
|
|
|
|
menu.addSortedChoices(recentChoices.map({ (recent: String) in choices[recent]! }), target: target, selector: selector)
|
|
|
|
menu.addItem(NSMenuItem.separatorItem())
|
|
|
|
var seen = [String: Bool]()
|
|
|
|
for prop in choices.values {
|
2014-12-08 04:35:58 +00:00
|
|
|
seen[prop["provenience"]!] = true
|
2014-12-07 05:20:57 +00:00
|
|
|
}
|
|
|
|
var sortedKeys = [String](seen.keys)
|
2015-11-16 01:56:33 +00:00
|
|
|
sortedKeys.sortInPlace { $0 < $1 }
|
2014-12-07 05:20:57 +00:00
|
|
|
for provenience in sortedKeys {
|
|
|
|
var subset = [ASPropertyEntry]()
|
|
|
|
for prop in choices.values {
|
|
|
|
if prop["provenience"] == provenience {
|
|
|
|
subset.append(prop)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let item = menu.addItemWithTitle(provenience, action: nil, keyEquivalent: "")!
|
|
|
|
let submenu = NSMenu()
|
|
|
|
submenu.autoenablesItems = false
|
|
|
|
submenu.addSortedChoices(subset, target: target, selector: selector)
|
|
|
|
menu.setSubmenu(submenu, forItem: item)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func buildBoardsMenu(menu:NSMenu, recentBoards:[String], target: AnyObject, selector: Selector) {
|
|
|
|
buildMenu(menu, choices:boards, recentChoices:recentBoards, target: target, selector: selector)
|
|
|
|
}
|
|
|
|
|
|
|
|
func buildProgrammersMenu(menu:NSMenu, recentProgrammers:[String], target: AnyObject, selector: Selector) {
|
|
|
|
buildMenu(menu, choices:programmers, recentChoices:recentProgrammers, target: target, selector: selector)
|
|
|
|
}
|
2014-11-28 13:18:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private let librariesInstance = ASLibraries()
|
2015-03-23 02:17:57 +00:00
|
|
|
class ASLibraries : NSObject {
|
2014-11-28 13:18:53 +00:00
|
|
|
class func instance() -> ASLibraries { return librariesInstance }
|
2015-02-14 16:43:20 +00:00
|
|
|
var directories = [String]()
|
|
|
|
var libraries = [String]()
|
2015-03-23 02:17:57 +00:00
|
|
|
var standardLib = [String]()
|
|
|
|
var contribLib = [String]()
|
|
|
|
override init() {
|
2014-11-28 13:18:53 +00:00
|
|
|
//
|
|
|
|
// Gather hardware directories
|
|
|
|
//
|
|
|
|
let userDefaults = NSUserDefaults.standardUserDefaults()
|
2015-03-23 02:17:57 +00:00
|
|
|
for sketchDir in userDefaults.objectForKey("Sketchbooks") as! [String] {
|
|
|
|
let librariesPath = sketchDir + "/libraries"
|
|
|
|
let dirs = subdirectories(librariesPath)
|
|
|
|
if dirs.count > 0 {
|
|
|
|
directories.append(librariesPath)
|
|
|
|
libraries += dirs
|
|
|
|
contribLib += dirs
|
|
|
|
}
|
|
|
|
}
|
2014-11-28 13:18:53 +00:00
|
|
|
if let arduinoPath = userDefaults.stringForKey("Arduino") {
|
|
|
|
let arduinoLibrariesPath = arduinoPath + "/Contents/Resources/Java/libraries"
|
|
|
|
let dirs = subdirectories(arduinoLibrariesPath)
|
|
|
|
if dirs.count > 0 {
|
|
|
|
directories.append(arduinoLibrariesPath)
|
|
|
|
libraries += dirs
|
2015-03-23 02:17:57 +00:00
|
|
|
standardLib += dirs
|
2014-11-28 13:18:53 +00:00
|
|
|
}
|
|
|
|
}
|
2015-03-23 02:17:57 +00:00
|
|
|
}
|
|
|
|
func addStandardLibrariesToMenu(menu: NSMenu) {
|
2015-11-16 01:56:33 +00:00
|
|
|
for (index,lib) in standardLib.enumerate() {
|
|
|
|
let menuItem = menu.addItemWithTitle((lib as NSString).lastPathComponent, action: "importStandardLibrary:", keyEquivalent: "")
|
2015-03-23 02:17:57 +00:00
|
|
|
menuItem?.target = self
|
|
|
|
menuItem?.tag = index
|
|
|
|
}
|
|
|
|
}
|
|
|
|
func addContribLibrariesToMenu(menu: NSMenu) {
|
2015-11-16 01:56:33 +00:00
|
|
|
for (index,lib) in contribLib.enumerate() {
|
|
|
|
let menuItem = menu.addItemWithTitle((lib as NSString).lastPathComponent, action: "importContribLibrary:", keyEquivalent: "")
|
2015-03-23 02:17:57 +00:00
|
|
|
menuItem?.target = self
|
|
|
|
menuItem?.tag = index
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@IBAction func importStandardLibrary(menuItem: AnyObject) {
|
|
|
|
if let tag = (menuItem as? NSMenuItem)?.tag {
|
|
|
|
NSApplication.sharedApplication().sendAction("importLibrary:", to: nil, from: standardLib[tag])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@IBAction func importContribLibrary(menuItem: AnyObject) {
|
|
|
|
if let tag = (menuItem as? NSMenuItem)?.tag {
|
|
|
|
NSApplication.sharedApplication().sendAction("importLibrary:", to: nil, from: contribLib[tag])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func validateUserInterfaceItem(anItem: NSValidatedUserInterfaceItem) -> Bool {
|
|
|
|
if let validator = NSApplication.sharedApplication().targetForAction("importLibrary:") as? NSUserInterfaceValidations {
|
|
|
|
return validator.validateUserInterfaceItem(anItem)
|
2014-11-28 13:18:53 +00:00
|
|
|
}
|
2015-03-23 02:17:57 +00:00
|
|
|
return false
|
2014-11-28 13:18:53 +00:00
|
|
|
}
|
|
|
|
}
|