@@ -88,6 +88,95 @@ defmodule Path do
8888 normalize FN . absname ( FN . absname ( path , relative_to ) , get_cwd ( path ) )
8989 end
9090
91+ @ doc """
92+ Returns the path type.
93+
94+ ## Unix examples
95+
96+ Path.type("/usr/local/bin") #=> :absolute
97+ Path.type("usr/local/bin") #=> :relative
98+ Path.type("../usr/local/bin") #=> :relative
99+
100+ ## Windows examples
101+
102+ Path.type("D:/usr/local/bin") #=> :absolute
103+ Path.type("usr/local/bin") #=> :relative
104+ Path.type("D:bar.ex") #=> :volumerelative
105+ Path.type("/bar/foo.ex") #=> :volumerelative
106+
107+ """
108+ def type ( name ) when is_list ( name ) or is_binary ( name ) do
109+ case :os . type ( ) do
110+ { :unix , _ } -> unix_pathtype ( name )
111+ { :win32 , _ } -> win32_pathtype ( name )
112+ end |> elem ( 0 )
113+ end
114+
115+ @ doc """
116+ Forces the path to be a relative path.
117+
118+ ## Unix examples
119+
120+ Path.relative("/usr/local/bin") #=> "usr/local/bin"
121+ Path.relative("usr/local/bin") #=> "usr/local/bin"
122+ Path.relative("../usr/local/bin") #=> "../usr/local/bin"
123+
124+ ## Windows examples
125+
126+ Path.relative("D:/usr/local/bin") #=> "usr/local/bin"
127+ Path.relative("usr/local/bin") #=> "usr/local/bin"
128+ Path.relative("D:bar.ex") #=> "bar.ex"
129+ Path.relative("/bar/foo.ex") #=> "bar/foo.ex"
130+
131+ """
132+ def relative ( name ) do
133+ case :os . type ( ) do
134+ { :unix , _ } -> unix_pathtype ( name )
135+ { :win32 , _ } -> win32_pathtype ( name )
136+ end |> elem ( 1 )
137+ end
138+
139+ defp unix_pathtype ( << ?/ , relative :: binary >> ) , do:
140+ { :absolute , relative }
141+ defp unix_pathtype ( [ ?/ | relative ] ) , do:
142+ { :absolute , relative }
143+ defp unix_pathtype ( [ list | rest ] ) when is_list ( list ) , do:
144+ unix_pathtype ( list ++ rest )
145+ defp unix_pathtype ( [ atom | rest ] ) when is_atom ( atom ) , do:
146+ unix_pathtype ( atom_to_list ( atom ) ++ rest )
147+ defp unix_pathtype ( relative ) , do:
148+ { :relative , relative }
149+
150+ @ slash [ ?/ , ?\\ ]
151+
152+ defp win32_pathtype ( [ list | rest ] ) when is_list ( list ) , do:
153+ win32_pathtype ( list ++ rest )
154+ defp win32_pathtype ( [ atom | rest ] ) when is_atom ( atom ) , do:
155+ win32_pathtype ( atom_to_list ( atom ) ++ rest )
156+ defp win32_pathtype ( [ char , list | rest ] ) when is_list ( list ) , do:
157+ win32_pathtype ( [ char | list ++ rest ] )
158+ defp win32_pathtype ( << c1 , c2 , relative :: binary >> ) when c1 in @ slash and c2 in @ slash , do:
159+ { :absolute , relative }
160+ defp win32_pathtype ( << c , relative :: binary >> ) when c in @ slash , do:
161+ { :volumerelative , relative }
162+ defp win32_pathtype ( << _letter , ?: , c , relative :: binary >> ) when c in @ slash , do:
163+ { :absolute , relative }
164+ defp win32_pathtype ( << _letter , ?: , relative :: binary >> ) , do:
165+ { :volumerelative , relative }
166+
167+ defp win32_pathtype ( [ c1 , c2 | relative ] ) when c1 in @ slash and c2 in @ slash , do:
168+ { :absolute , relative }
169+ defp win32_pathtype ( [ c | relative ] ) when c in @ slash , do:
170+ { :volumerelative , relative }
171+ defp win32_pathtype ( [ c1 , c2 , list | rest ] ) when is_list ( list ) , do:
172+ win32_pathtype ( [ c1 , c2 | list ++ rest ] )
173+ defp win32_pathtype ( [ _letter , ?: , c | relative ] ) when c in @ slash , do:
174+ { :absolute , relative }
175+ defp win32_pathtype ( [ _letter , ?: | relative ] ) , do:
176+ { :volumerelative , relative }
177+ defp win32_pathtype ( relative ) , do:
178+ { :relative , relative }
179+
91180 @ doc """
92181 Returns the given `path` relative to the given `from` path.
93182
0 commit comments