Skip to content

Instantly share code, notes, and snippets.

@brookinc
Last active December 29, 2018 05:43
Show Gist options
  • Save brookinc/02c0694009b736526848bd93803c1190 to your computer and use it in GitHub Desktop.
Save brookinc/02c0694009b736526848bd93803c1190 to your computer and use it in GitHub Desktop.
A simple script to demonstrate some basics of Swift scripting.
#!/usr/bin/swift
// shell.swift
// A simple script to demonstrate some basics of Swift scripting.
import Foundation
// Docs: https://developer.apple.com/documentation/foundation
// ...and: https://github.com/apple/swift-corelibs-foundation/blob/master/Docs/Status.md
extension CommandLine {
// credit: https://stackoverflow.com/a/50035059/5673556
static func run(_ command: String) -> String {
let task = Process()
task.launchPath = "/bin/bash"
task.arguments = ["-c", command]
let pipe = Pipe()
task.standardOutput = pipe
task.launch()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output = String(data: data, encoding: .utf8)!
return output
}
}
let scriptName = CommandLine.arguments[0]
let currentDir = FileManager.default.currentDirectoryPath
let suffix = (CommandLine.argc > 1) ? ":" : ""
print("\(scriptName) launched from \(currentDir) with \(CommandLine.argc - 1) additional arguments\(suffix)")
if !suffix.isEmpty {
dump(CommandLine.arguments)
}
var showHidden = false
var maxToPrint = 10
var filenamePattern: NSRegularExpression?
var showPermissions = false
for argument in CommandLine.arguments {
if argument == "-a" {
showHidden = true
} else if argument == "-e" {
showPermissions = true
} else if argument.hasPrefix("-m=") {
let startIndex = argument.index(after: argument.index(of: "=")!) // TODO: Swift 4.2 renames String.index(of:) to String.firstIndex(of:)
if let maxCount = Int(argument.suffix(from: startIndex)) {
maxToPrint = maxCount
}
} else if argument.hasPrefix("-p=") {
let startIndex = argument.index(after: argument.index(of: "=")!) // TODO: Swift 4.2 renames String.index(of:) to String.firstIndex(of:)
// Note: we don't support whitespace here yet (even escaped), or quoted patterns (ie. any quotes will be included)
let pattern = String(argument.suffix(from: startIndex))
filenamePattern = try? NSRegularExpression(pattern: pattern, options: .caseInsensitive)
}
}
var numPrinted = 0
func printFiles(path: URL) {
guard showHidden || !path.lastPathComponent.hasPrefix(".") else {
return
}
guard maxToPrint <= 0 || numPrinted < maxToPrint else {
return
}
var doPrint = true
if let regex = filenamePattern {
let filename = path.lastPathComponent
let filenameNS = NSString(string: path.lastPathComponent)
if regex.firstMatch(in: String(filename), range: NSRange(location: 0, length: filenameNS.length)) == nil {
// we still want to recurse on non-matching directories, so wipe the print flag here instead of returning
doPrint = false
}
}
if doPrint {
var output = path.path
if showPermissions {
let shellOutput = CommandLine.run("ls -lda \(path.path)")
let columns = shellOutput.split(separator: " ")
if columns.count > 0 {
output += " -> \(columns[0])"
}
}
print(output)
numPrinted += 1
if numPrinted == maxToPrint {
print("Maximum output of \(maxToPrint) reached -- use `-m=NUMBER` to set a higher maximum, or `-m=0` for no maximum.")
}
}
if path.hasDirectoryPath {
var contents = try! FileManager.default.contentsOfDirectory(at: path, includingPropertiesForKeys: nil)
contents.sort {
return $0.lastPathComponent.lowercased() <= $1.lastPathComponent.lowercased()
}
for item in contents {
printFiles(path: item)
}
}
}
let currentDirectory = URL(fileURLWithPath: FileManager.default.currentDirectoryPath)
printFiles(path: currentDirectory)
# force linefeed (Unix-style) line endings for all .swift files, to prevent SwiftLint
# vertical_whitespace warnings (and line number mismatches) on Windows host machines
*.swift eol=lf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment