user187676
user187676

Reputation:

Substitute user path with tilde in URL

Assume a file URL containing /Users/me/a/b. Is there a better method than a naive string replace using NSHomeDirectory() to get the short form ~/a/b?

This is what I'm currently using

.replacingOccurrences(of: NSHomeDirectory(), with: "~", options: .anchored, range: nil)

PS: No NSString casting!

Upvotes: 5

Views: 1000

Answers (4)

juliand665
juliand665

Reputation: 3334

I noticed this question doesn't have an accepted answer yet, and I ran into the same issue. I tried the NSString methods, but those didn't work in a sandboxed context anyway, and the getpwuid method felt… wrong. So here's a pure Swift solution that's only really hardcoded insofar as it assumes the sandbox root to share the first 3 path components (/, Users, your username) with your actual home directory:

extension URL {
    var pathAbbreviatingWithTilde: String {
        // find home directory path (more difficulty because we're sandboxed, so it's somewhere deep in our actual home dir)
        let sandboxedHomeDir = FileManager.default.homeDirectoryForCurrentUser
        let components = sandboxedHomeDir.pathComponents
        guard components.first == "/" else { return path }
        let homeDir = "/" + components.dropFirst().prefix(2).joined(separator: "/")
        
        // replace home dir in path with tilde for brevity and aesthetics
        guard path.hasPrefix(homeDir) else { return path }
        return "~" + path.dropFirst(homeDir.count)
    }
}

Upvotes: 0

Vlad
Vlad

Reputation: 6732

If you are in Sandboxed app then usage of getpwuid function is needed.

extension FileManager {
   /// Returns path to real home directory in Sandboxed application
   public var realHomeDirectory: String? {
      if let home = getpwuid(getuid()).pointee.pw_dir {
         return string(withFileSystemRepresentation: home, length: Int(strlen(home)))
      }
      return nil
   }
}

Example usage:

func configure(url: URL) {
  ...
  var directory = url.path.deletingLastPathComponent
  toolTip = url.path
  if let homeDir = FileManager.default.realHomeDirectory {
     // FYI: `url.path.abbreviatingWithTildeInPath` not working for sandboxed apps.
     let abbreviatedPath = url.path.replacingFirstOccurrence(of: homeDir, with: "~")
     directory = abbreviatedPath.deletingLastPathComponent
     toolTip = abbreviatedPath
  }
  directoryLabel.text = directory
}

More about getpwuid function: How do I get the users home directory in a sandboxed app?


Result of usage in NSView:

enter image description here

Upvotes: 3

Keith Knauber
Keith Knauber

Reputation: 802

NSPathUtilities - (NSString *)stringByAbbreviatingWithTildeInPath; - (NSString *)stringByExpandingTildeInPath;

[blueprintsDict writeToFile: [[NSString stringWithFormat:@"~/MbPatchBlueprints.plist"] stringByExpandingTildeInPath] atomically:YES];

Upvotes: 0

DDP
DDP

Reputation: 2563

How about converting to NSString and then abbreviating it with:

var path = url.path as NSString!
var abbrevPath=path?.abbreviatingWithTildeInPath

Upvotes: 0

Related Questions