#FEATURE by cg
class: Filename
added: #pathNameRelativeFrom:
comment/format in:
#pathName
#separator
--- 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