Moderator: parsing commandline arguments in Swift

There are a lot of command line argument parsers written in Swift available on Github, so when I needed one for a client project I was surprised I could not find any which fulfilled these requirements:


  • handle --tag=value.
  • treat unrecognised arguments as an error and list them.

Nor could I find any where it would be relatively easy to add these features, since most just loop through the arguments from first to last and have one big function trying to find out what to do with each of them. That becomes messy quickly.


I think it’s much simpler to create multiple small argument parsers, where each one in turn takes in the list of arguments, removes the ones it wants to handle and passes the rest on to the next one. Any arguments left over are then unrecognised and can be handled accordingly. This way the end user does not need to worry about the order of the arguments. The developer however needs to be careful about the order of the parsers.

Read More

FileSmith: Type-safe file handling in Swift

Dealing with file paths in Swift is cumbersome. Using only the standard library leaves us with Strings, which we can join together or split by /. It gets the job done but it’s not pretty, and we need a separate type so our methods can accept file paths exclusively and not just any old String. Foundation gives us this in NSURL/URL, which are also used for internet URLs so their method names are very general and long. E.g. url.deletingPathExtension().lastPathComponent to return the file name without the extension.

The Swift Package Manager has separate types for absolute paths and relative paths, because in their opinion these are fundamentally different. I can see their point, but I think it should be up to the callers of an API and not the creators whether to use absolute or relative paths.

The best alternative I’ve been able to find is JohnSundell/Files, because it gets an important thing right: it differentiates between files and directories. These are fundamentally different things (even though the internal representation of their paths are identical) and should have different types with different functionalities. You can’t read from or write to a directory itself, nor can you add a directory to a file.

What I am looking for however has separate types not only for files and folders, but also for paths (which may or may not exist) and filesystem items (which do), and for files you just want to read from and not change and files you want to write to, rename, move and/or delete. Because filesystem access, maybe more than any other task solved by programming, has the potential to irrevocably mess things up. And one way to prevent this is extra type safety, leading to fewer programmer errors.

So I made the FileSmith library with FilePath/DirectoryPath, ReadableFile/WritableFile and Directory.

Read More

Splitting text read piece by piece

Swift version 2.1.

In the previous post we implemented lazy splitting of collections, very useful for say splitting large texts into lines. But in SwiftShell I need the same functionality for text which is acquired piecemeal, like the output of a long-running shell command read sequentially, when needed. Because shell commands which are piped together in the terminal should get to work right away, and not just hang around waiting for the previous command to finish. Like this:

 

Both scripts start at the same time. The left one uses the functionality implemented below, while the right one reads the entire input into a string first, and therefore has to wait for the ‘linemaker’ command to finish before doing any actual work.

Read More

Splitting text and collections lazily in Swift

Swift version 2.1

There are already methods for splitting collections in the Swift Standard Library, but they do all the work immediately and return the results in an array. When dealing with large strings, or streams of text, I find it better to do the work lazily, when needed. The overall performance is not necessarily better, but it is smoother, as you get the first results immediately instead of having to wait a little while and then get everything at once. And memory usage is lower, no need to store everything in an array first.

Read More

Swift: mixing default values and variadic parameters.

Update:

As of Xcode 7 beta 6, Swift no longer requires variadic parameters to be last in the function definition. Also argument labels are no longer required when combined with parameters with default values. So this all works fine now:

The rest of this post is deprecated.

Read More