|
| 1 | +import Foundation |
| 2 | + |
| 3 | +public enum SystemActionHeading { |
| 4 | + case section |
| 5 | + case phase |
| 6 | +} |
| 7 | + |
| 8 | +/// `SystemAction` provides some common system-level actions typically needed of command-line utilities. It is a protocol that abstracts the intent of the action from the implementation of the action. |
| 9 | +/// |
| 10 | +/// It is particularly well suited to supporting verbose and dry-run modes for command-line utilities. This can be accomplished with code like this: |
| 11 | +/// |
| 12 | +/// ``` |
| 13 | +/// let actions: SystemAction |
| 14 | +/// if enableDryRun { |
| 15 | +/// actions = CompositeAction([SystemActionPrint()]) |
| 16 | +/// } else if verbose { |
| 17 | +/// actions = CompositeAction([SystemActionPrint(), SystemActionReal()]) |
| 18 | +/// } else { |
| 19 | +/// actions = CompositeAction([SystemActionReal()]) |
| 20 | +/// } |
| 21 | +/// ``` |
| 22 | +/// |
| 23 | +public protocol SystemAction { |
| 24 | + /// Declare a heading for the next set of actions |
| 25 | + func heading(_ type: SystemActionHeading, _ string: String) |
| 26 | + |
| 27 | + /// Attempt to create a directory |
| 28 | + func createDirectory(url: URL) throws |
| 29 | + |
| 30 | + /// Attempt to create a file containing the given string |
| 31 | + func createFile(fileUrl: URL, content: String) throws |
| 32 | + |
| 33 | + /// Execute a program and print the results to stdout |
| 34 | + func runAndPrint(path: String?, command: [String]) throws |
| 35 | +} |
| 36 | + |
| 37 | +public extension SystemAction { |
| 38 | + /// Print the title of a section |
| 39 | + /// - Parameter string: title to print |
| 40 | + func section(_ string: String) { |
| 41 | + self.heading(.section, string) |
| 42 | + } |
| 43 | + |
| 44 | + /// Print the title of a phase |
| 45 | + /// - Parameter string: title to print |
| 46 | + func phase(_ string: String) { |
| 47 | + self.heading(.phase, string) |
| 48 | + } |
| 49 | + |
| 50 | + /// Create a file at a given path. |
| 51 | + /// |
| 52 | + /// This will overwrite existing files. |
| 53 | + /// - Parameters: |
| 54 | + /// - file: fileURL to create |
| 55 | + /// - contentBuilder: A closure that returns the content to write into the file. |
| 56 | + /// - Throws: any problems in creating file. |
| 57 | + func createFile(fileUrl: URL, _ contentBuilder: ()->String) throws { |
| 58 | + let content = contentBuilder() |
| 59 | + try self.createFile(fileUrl: fileUrl, content: content) |
| 60 | + } |
| 61 | + |
| 62 | + /// Execute the given command and show the results |
| 63 | + /// - Parameters: |
| 64 | + /// - path: If not-nil, this will be the current working directory when the command is exectued. |
| 65 | + /// - command: Command to execute |
| 66 | + /// - Throws: any problems in executing the command or if the command has a non-0 return code |
| 67 | + func runAndPrint(path: String?=nil, command: String...) throws { |
| 68 | + try self.runAndPrint(path: path, command: command) |
| 69 | + } |
| 70 | +} |
0 commit comments