fsaar/filesize

View on GitHub
Sources/filesizeCore/CommandLineParser.swift

Summary

Maintainability
A
25 mins
Test Coverage
//
//  CommandLineParser.swift
//  filesizePackageDescription
//
//  Created by Frank Saar on 21/12/2017.
//

import Foundation


public class CommandLineParser {
    
    public enum Result : Error {
        case invalidFormat
        case invalidPath
        case notEnoughArguments
        public var message: String? {
            switch self {
            case .notEnoughArguments:
                return "Invalid number of arguments"
            case .invalidPath:
                return "Invalid path"
            default:
                return nil
            }
        }
    }
    
    public enum Option : String {
        case swift
        case objc
        case help
        case limit
        public init?(rawValue : String) {
            guard rawValue.hasPrefix("--") else {
                return nil
            }
            let startIndex = rawValue.index(rawValue.startIndex,offsetBy:2)
            let optionString = rawValue[startIndex...].lowercased()
            switch optionString {
            case Option.swift.rawValue:
                self =  .swift
            case Option.objc.rawValue:
                self = .objc
            case Option.help.rawValue:
                self = .help
            case Option.limit.rawValue:
                self = .limit
            default:
                return nil
            }
        }
        
        public var directoryParserOption : FileContentProvider.FileType? {
            switch self {
            case .swift:
                return .swift
            case .objc:
                return .objc
            default:
                return nil
            }
        }
    }
    
    let arguments : [String]
    public init(arguments : [String]) {
        self.arguments = arguments
    }
    
    public func parseCommandLine() throws -> (URL?,Int?,Option?) {
        if arguments.count >= 2,let limitOption = Option(rawValue: arguments[1]), limitOption == .help {
           return (nil,nil,.help)
        }
        guard arguments.count >= 4 else {
            throw Result.notEnoughArguments
        }
        guard let limitOption = Option(rawValue: arguments[2]), limitOption == .limit else {
            throw Result.invalidFormat
        }
        guard let limit = Int(arguments[3]) else {
            throw Result.invalidFormat
        }
        let path = arguments[1]
        guard let url = url(with: path) else {
            throw Result.invalidPath
        }
        guard arguments.count > 4, let fileTypeOption = Option(rawValue: arguments[4]), Set<Option>([.swift,.objc]).contains(fileTypeOption) else {
            return (url,limit,nil)
        }
        return (url,limit,fileTypeOption)
    }
}

fileprivate extension CommandLineParser {
    
    func url(with path : String) -> URL? {
        let isRelativePath = path.hasPrefix(".")
        let relativePath = isRelativePath ? URL(fileURLWithPath: FileManager.default.currentDirectoryPath) : nil
        let url = URL(fileURLWithPath: path, relativeTo: relativePath)
        var isDirectory = ObjCBool(false)
        guard FileManager.default.fileExists(atPath: url.path, isDirectory: &isDirectory),isDirectory.boolValue else {
            return nil
        }
        return url
    }
    
}