#FEATURE by cg
authorClaus Gittinger <cg@exept.de>
Mon, 01 Jan 2018 11:58:03 +0100
changeset 22403 a4396e2a038e
parent 22402 65b1d7257fbd
child 22404 698e01ed8d59
#FEATURE by cg class: Filename added: #pathNameRelativeFrom: comment/format in: #pathName #separator
Filename.st
--- a/Filename.st	Mon Jan 01 11:02:28 2018 +0100
+++ b/Filename.st	Mon Jan 01 11:58:03 2018 +0100
@@ -4994,6 +4994,11 @@
 
     ^ self species separator
 
+    "
+     UnixFilename separator 
+     PCFilename separator
+    "
+
     "Modified: 29.2.1996 / 20:52:01 / cg"
 !
 
@@ -5702,14 +5707,6 @@
      no compression will be done (for now; this may change).
      See also: name"
 
-
-"/    sep := self class separator.
-"/    (nameString startsWith:sep) ifTrue:[
-"/        parentName := self class parentDirectoryName.
-"/        (nameString findString:parentName) == 0 ifTrue:[
-"/            ^ nameString
-"/        ]
-"/    ].
     ^ OperatingSystem pathNameOf:(self species nameWithSpecialExpansions:nameString).
 
     "
@@ -5725,6 +5722,62 @@
     "Modified: 27.4.1996 / 18:19:52 / cg"
 !
 
+pathNameRelativeFrom:anotherDirectoriesFilename
+    "return the pathname of the receiver,
+     but relative from another directory.
+     I.e. if the receiver is /a/b/c
+     and the argument is /a/x/y,
+     then the relative path to the receiver as seen from the argument is ../../b/c"
+
+    |myPath otherDir otherPath rest prefix|
+
+    myPath := self pathName.
+    otherDir := anotherDirectoriesFilename asFilename.
+    prefix := ''.
+    [
+        otherPath := otherDir pathName.
+        "/ if I am below:
+        (myPath startsWith:otherPath) ifTrue:[
+            rest := (myPath copyFrom:otherPath size+1).
+            rest isEmpty ifTrue:[^ prefix,'.' ].
+            (rest startsWith:self separator) ifTrue:[^ prefix,(rest copyFrom:2) ].
+            ^ prefix,rest
+        ].
+        prefix := prefix,'..',self separator.
+        otherDir := otherDir directory.
+    ] loop
+
+    "
+     self assert:('/a' asFilename pathNameRelativeFrom:'/') = 'a'  
+     self assert:('/a/b' asFilename pathNameRelativeFrom:'/') = 'a/b'  
+
+     self assert:('/a' asFilename pathNameRelativeFrom:'/a') = '.'  
+     self assert:('/a/b' asFilename pathNameRelativeFrom:'/a') = 'b'  
+     self assert:('/a/b/c' asFilename pathNameRelativeFrom:'/a') = 'b/c'  
+
+     self assert:('/a/' asFilename pathNameRelativeFrom:'/a') = '.'  
+     self assert:('/a/b/' asFilename pathNameRelativeFrom:'/a') = 'b'  
+     self assert:('/a/b/c/' asFilename pathNameRelativeFrom:'/a') = 'b/c'  
+
+     self assert:('/a' asFilename pathNameRelativeFrom:'/a/') = '.'  
+     self assert:('/a/b' asFilename pathNameRelativeFrom:'/a/') = 'b'  
+     self assert:('/a/b/c' asFilename pathNameRelativeFrom:'/a/') = ''b/c''  
+
+     self assert:('/a/' asFilename pathNameRelativeFrom:'/a/') = '.'  
+     self assert:('/a/b/' asFilename pathNameRelativeFrom:'/a/') = 'b'  
+     self assert:('/a/b/c/' asFilename pathNameRelativeFrom:'/a/') = 'b/c'  
+
+     self assert:('/a' asFilename pathNameRelativeFrom:'/b') = '../a'  
+     self assert:('/a/b/' asFilename pathNameRelativeFrom:'/b') = '../a/b'  
+     self assert:('/a/b/c/' asFilename pathNameRelativeFrom:'/b') = '../a/b/c'  
+
+     self assert:('/a/b/' asFilename pathNameRelativeFrom:'/a') = 'b'  
+     self assert:('/a/b/c/' asFilename pathNameRelativeFrom:'/a') = 'b/c'  
+
+     self assert:('/a/b/c/d' asFilename pathNameRelativeFrom:'/a/x/y/z') = '../../../b/c/d'  
+    "
+!
+
 physicalFilename
     "return the fileName representing the physical file as represented by the receiver,
      If the receiver represents a symbolic link, that's the fileName of the