Skip to content

Instantly share code, notes, and snippets.

@hoonsubin
Last active March 3, 2021 09:12
Show Gist options
  • Save hoonsubin/d8facc63d5229885e96295f24d56242a to your computer and use it in GitHub Desktop.
Save hoonsubin/d8facc63d5229885e96295f24d56242a to your computer and use it in GitHub Desktop.
A simple utility to create a full path from the given point with all the directory change
using System.Collections.Generic;
using System.IO;
using System;
namespace HoonKim.Editor
{
public static class UnityPathUtil
{
/// <summary>
/// Path utility that combines the original path with the relative path with all the directory change operations.
/// This is a simple implementation focusing on readability, but we can expand this class to do more.
/// </summary>
/// <param name="originPath">The reference path</param>
/// <param name="relativeTarget">Relative path from the origin path</param>
/// <param name="separator">File separator. Default is the Unix style</param>
/// <returns>The full path to the given relative path</returns>
public static string GetFullPathFromRelative(string originPath, string relativeTarget, char separator = '/')
{
// note: we assume the root is `Assets/` as that is the default for the editor
// if you want this to work for different platforms and in runtime, you can use the
string[] sourceFolders = originPath.Split(separator);
string[] destFolders = relativeTarget.Split(separator);
// ensure that the provided relative target is not an absolute path
if (destFolders[0] != "." && destFolders[0] != "..")
{
throw new Exception($"{relativeTarget} is not a relative path");
}
// directories are easier to work as a stack
Stack<string> fullPathStack = new Stack<string>(sourceFolders);
for (int i = sourceFolders.Length - 1; i >= 0; i--)
{
if (string.IsNullOrEmpty(sourceFolders[i]) || Path.HasExtension(sourceFolders[i]))
{
// change all the folders as an array and remove any empty elements (in case of a leading `/` to denote that it's a folder)
fullPathStack.Pop();
}
else
{
// if the path is valid,
break;
}
}
for (int i = 0; i < destFolders.Length; i++)
{
string currentFolder = destFolders[i];
if (currentFolder == "..")
{
// go up one level
fullPathStack.Pop();
}
else if (currentFolder == ".")
{
continue;
}
// checking for empty elements for corner cases
else if (!string.IsNullOrEmpty(currentFolder))
{
// add the current folder
fullPathStack.Push(currentFolder);
}
}
// Stack.ToArray() method is LIFO of the elements, so we need to flip it
// note: the Array.Reverse() function mutates the passed array instead of returning a new one
string[] fullPathArray = fullPathStack.ToArray();
Array.Reverse(fullPathArray);
return String.Join(separator.ToString(), fullPathArray);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment