AVRSack/AVRsack/ASHardware.swift

210 lines
9.3 KiB
Swift
Raw Normal View History

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) {
2016-11-13 11:03:51 +00:00
for choice in choices.sorted(by: { $0["name"] < $1["name"] }) {
let item = self.addItem(withTitle: choice["name"]!, action: selector, keyEquivalent: "")
item.target = target
2014-12-07 05:20:57 +00:00
}
}
}
2015-02-14 16:43:20 +00:00
private func subdirectories(path: String) -> [String] {
2016-11-13 11:03:51 +00:00
let fileManager = FileManager.default
2015-02-14 16:43:20 +00:00
var subDirs = [String]()
2014-11-24 01:02:29 +00:00
var isDir : ObjCBool = false
2016-11-13 11:03:51 +00:00
if let items = try? fileManager.contentsOfDirectory(atPath: path) {
2015-11-16 01:56:33 +00:00
for item in items {
2014-11-24 01:02:29 +00:00
let subPath = path+"/"+item
2016-11-13 11:03:51 +00:00
if fileManager.fileExists(atPath: subPath, isDirectory: &isDir) && isDir.boolValue {
2014-11-24 01:02:29 +00:00
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
//
2016-11-13 11:03:51 +00:00
let userDefaults = UserDefaults.standard
if let arduinoPath = userDefaults.string(forKey: "Arduino") {
2014-11-24 01:02:29 +00:00
let arduinoHardwarePath = arduinoPath + "/Contents/Resources/Java/hardware"
2016-11-13 11:03:51 +00:00
directories += subdirectories(path: arduinoHardwarePath)
2014-11-24 01:02:29 +00:00
}
2016-11-13 11:03:51 +00:00
for sketchDir in userDefaults.object(forKey: "Sketchbooks") as! [String] {
2014-11-24 01:02:29 +00:00
let hardwarePath = sketchDir + "/hardware"
2016-11-13 11:03:51 +00:00
directories += subdirectories(path: hardwarePath)
2014-11-24 01:02:29 +00:00
}
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]()
2016-11-13 11:03:51 +00:00
for line in boardsFile.components(separatedBy: "\n") {
if let match = property.firstMatch(in: line, options: .anchored, range: NSMakeRange(0, line.utf16.count)) {
2015-11-16 01:56:33 +00:00
let nsline = line as NSString
2016-11-13 11:03:51 +00:00
let board = nsline.substring(with: match.rangeAt(1)) as String
let property = nsline.substring(with: match.rangeAt(2)) as String
let value = nsline.substring(with: match.rangeAt(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]()
2016-11-13 11:03:51 +00:00
for line in programmersFile.components(separatedBy: "\n") {
if let match = property.firstMatch(in: line, options: .anchored, range: NSMakeRange(0, line.utf16.count)) {
2015-11-16 01:56:33 +00:00
let nsline = line as NSString
2016-11-13 11:03:51 +00:00
let programmer = nsline.substring(with: match.rangeAt(1))
let property = nsline.substring(with: match.rangeAt(2))
let value = nsline.substring(with: match.rangeAt(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()
2016-11-13 11:03:51 +00:00
menu.addItem(withTitle: "Title", action: nil, keyEquivalent: "")
2014-12-07 05:20:57 +00:00
if choices.count <= 10 {
2016-11-13 11:03:51 +00:00
menu.addSortedChoices(choices: [ASPropertyEntry](choices.values), target: target, selector: selector)
2014-12-07 05:20:57 +00:00
} else {
2016-11-13 11:03:51 +00:00
menu.addSortedChoices(choices: recentChoices.flatMap({ (recent: String) in choices[recent] }), target: target, selector: selector)
menu.addItem(NSMenuItem.separator())
2014-12-07 05:20:57 +00:00
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)
2016-11-13 11:03:51 +00:00
sortedKeys.sort { $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)
}
}
2016-11-13 11:03:51 +00:00
let item = menu.addItem(withTitle: provenience, action: nil, keyEquivalent: "")
2014-12-07 05:20:57 +00:00
let submenu = NSMenu()
submenu.autoenablesItems = false
2016-11-13 11:03:51 +00:00
submenu.addSortedChoices(choices: subset, target: target, selector: selector)
menu.setSubmenu(submenu, for: item)
2014-12-07 05:20:57 +00:00
}
}
}
func buildBoardsMenu(menu:NSMenu, recentBoards:[String], target: AnyObject, selector: Selector) {
2016-11-13 11:03:51 +00:00
buildMenu(menu: menu, choices:boards, recentChoices:recentBoards, target: target, selector: selector)
2014-12-07 05:20:57 +00:00
}
func buildProgrammersMenu(menu:NSMenu, recentProgrammers:[String], target: AnyObject, selector: Selector) {
2016-11-13 11:03:51 +00:00
buildMenu(menu: menu, choices:programmers, recentChoices:recentProgrammers, target: target, selector: selector)
2014-12-07 05:20:57 +00:00
}
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
//
2016-11-13 11:03:51 +00:00
let userDefaults = UserDefaults.standard
for sketchDir in userDefaults.object(forKey: "Sketchbooks") as! [String] {
2015-03-23 02:17:57 +00:00
let librariesPath = sketchDir + "/libraries"
2016-11-13 11:03:51 +00:00
let dirs = subdirectories(path: librariesPath)
2015-03-23 02:17:57 +00:00
if dirs.count > 0 {
directories.append(librariesPath)
libraries += dirs
contribLib += dirs
}
}
2016-11-13 11:03:51 +00:00
if let arduinoPath = userDefaults.string(forKey: "Arduino") {
2014-11-28 13:18:53 +00:00
let arduinoLibrariesPath = arduinoPath + "/Contents/Resources/Java/libraries"
2016-11-13 11:03:51 +00:00
let dirs = subdirectories(path: arduinoLibrariesPath)
2014-11-28 13:18:53 +00:00
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) {
2016-11-13 11:03:51 +00:00
for (index,lib) in standardLib.enumerated() {
2016-11-14 00:37:13 +00:00
let menuItem = menu.addItem(withTitle: (lib as NSString).lastPathComponent, action: #selector(ASLibraries.importStandardLibrary(menuItem:)), keyEquivalent: "")
2016-11-13 11:03:51 +00:00
menuItem.target = self
menuItem.tag = index
2015-03-23 02:17:57 +00:00
}
}
func addContribLibrariesToMenu(menu: NSMenu) {
2016-11-13 11:03:51 +00:00
for (index,lib) in contribLib.enumerated() {
2016-11-14 00:37:13 +00:00
let menuItem = menu.addItem(withTitle: (lib as NSString).lastPathComponent, action: #selector(ASLibraries.importContribLibrary(menuItem:)), keyEquivalent: "")
2016-11-13 11:03:51 +00:00
menuItem.target = self
menuItem.tag = index
2015-03-23 02:17:57 +00:00
}
}
2016-11-14 00:37:13 +00:00
@IBAction func importStandardLibrary(menuItem: AnyObject) {
2015-03-23 02:17:57 +00:00
if let tag = (menuItem as? NSMenuItem)?.tag {
2016-11-13 11:03:51 +00:00
NSApplication.shared().sendAction(#selector(ASProjDoc.importLibrary(_:)), to: nil, from: standardLib[tag])
2015-03-23 02:17:57 +00:00
}
}
2016-11-14 00:37:13 +00:00
@IBAction func importContribLibrary(menuItem: AnyObject) {
2015-03-23 02:17:57 +00:00
if let tag = (menuItem as? NSMenuItem)?.tag {
2016-11-13 11:03:51 +00:00
NSApplication.shared().sendAction(#selector(ASProjDoc.importLibrary(_:)), to: nil, from: contribLib[tag])
2015-03-23 02:17:57 +00:00
}
}
func validateUserInterfaceItem(anItem: NSValidatedUserInterfaceItem) -> Bool {
2016-11-13 11:03:51 +00:00
if let validator = NSApplication.shared().target(forAction: #selector(ASProjDoc.importLibrary(_:))) as? NSUserInterfaceValidations {
2015-03-23 02:17:57 +00:00
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
}
}