# HG changeset patch # User Claus Gittinger # Date 825624088 -3600 # Node ID 6f7b6c18a7481486a5f33c80a9d442b275d8ea27 # Parent c535c5a73cbad411bbee7c0a09386bb31cf91595 new goodies (bells & whistles upon claus's request) diff -r c535c5a73cba -r 6f7b6c18a748 Filename.st --- a/Filename.st Thu Feb 29 18:29:46 1996 +0100 +++ b/Filename.st Thu Feb 29 21:01:28 1996 +0100 @@ -216,6 +216,42 @@ " ! +fromComponents:aCollectionOfDirectoryNames + "create & return a new filename from components given in + aCollectionOfDirectoryNames. If the first component is the name of the + root directory (i.e. '/') an absolute path-filename is returned." + + |sep s| + + sep := self separator asString. + s := ''. + aCollectionOfDirectoryNames keysAndValuesDo:[:index :component | + index == 1 ifTrue:[ + (component ~= sep + or:[aCollectionOfDirectoryNames size == 1]) ifTrue:[ + s := s , component + ] + ] ifFalse:[ + s := s , '/' , component + ]. + ]. + ^ self named:s + + " + Filename fromComponents:#('/' 'foo' 'bar' 'baz') + Filename fromComponents:#('foo' 'bar' 'baz') + Filename fromComponents:#('/') + + Filename fromComponents: + (Filename components:('.' asFilename pathName)) + + Filename fromComponents: + (Filename components:('.' asFilename name)) + " + + "Modified: 29.2.1996 / 20:18:34 / cg" +! + fromUser "show a box to enter a filename. Return a filename instance or nil (if cancel was pressed)." @@ -231,6 +267,26 @@ " ! +homeDirectory + "return your homeDirectory. + Some OperatingSystems do not support this - on those, the defaultDirectory + (which is the currentDirectory) is returned." + + |s| + + s := OperatingSystem getHomeDirectory. + s isNil ifTrue:[ + ^ self defaultDirectory + ]. + ^ s asFilename + + " + Filename homeDirectory + " + + "Modified: 29.2.1996 / 21:00:31 / cg" +! + named:aString "return a filename for a directory named aString. This is the same as 'aString asFilename'." @@ -327,6 +383,30 @@ !Filename class methodsFor:'queries'! +components:aString + "separate the pathName given by aString into + a collection containing the directory components and the files name as + the final component. + If the argument names an absolute path, the first component will be the + name of the root directory (i.e. '/')." + + |components| + + components := aString asCollectionOfSubstringsSeparatedBy:(self separator). + components first isEmpty ifTrue:[ + components at:1 put:(self separator asString) + ]. + ^ components + + + " + Filename components:'/foo/bar/baz' + Filename components:'foo/bar/baz' + " + + "Modified: 29.2.1996 / 20:06:38 / cg" +! + defaultClass "ST-80 compatibility: in ST-80, different subclasses of Filename are used for different @@ -445,6 +525,16 @@ "Modified: 7.9.1995 / 10:44:56 / claus" ! +maxLength + "return the maximum number of characters a filename may be in size. + This depends on the OperatingSystem." + + ^ OperatingSystem maxFileNameLength + + "Created: 29.2.1996 / 20:57:11 / cg" + "Modified: 29.2.1996 / 20:57:46 / cg" +! + parentDirectoryName "return the name used for the parent directory. This is '..' for unix and dos-like systems. @@ -1046,18 +1136,6 @@ !Filename methodsFor:'file utilities'! -contentsOfEntireFile - "return the contents of the file as a string" - - |s contents| - - s := self readStream. - [ - contents := s contents - ] valueNowOrOnUnwindDo:[s close]. - ^ contents -! - edit "start an editView on the file represented by the receiver" @@ -1078,8 +1156,9 @@ construct:subname "taking the receiver as a directory name, construct a new - filename for an entry within this directory (i.e. for a file - or a subdirectory in that directory)." + filename for an entry within this directory + (i.e. for a file or a subdirectory in that directory). + See also: #withSuffix: (which is different, but often needed)" ^ (self constructString:subname) asFilename @@ -1089,19 +1168,21 @@ '/usr/tmp' asFilename construct:'foo' '/foo/bar' asFilename construct:'baz' " + + "Modified: 29.2.1996 / 20:55:06 / cg" ! constructString:subname "taking the receiver as a directory name, construct a new - filenames string for an entry within this directory (i.e. for a file - or a subdirectory in that directory)." + filenames string for an entry within this directory + (i.e. for a file or a subdirectory in that directory)." |sepString| sepString := self class separator asString. nameString = sepString ifTrue:[ - "I am the root" - ^ sepString , subname + "I am the root" + ^ sepString , subname ]. ^ nameString , sepString , subname asString @@ -1113,6 +1194,7 @@ " "Modified: 7.9.1995 / 10:15:22 / claus" + "Modified: 29.2.1996 / 20:55:18 / cg" ! ! !Filename methodsFor:'misc'! @@ -1121,14 +1203,19 @@ "this allows filenames to understand how names are concatenated. Returns a string consisting of the receivers name, concatenated by aString. Notice this is NOT the same as construct:, which inserts - a directory delimiter and returns a new fileName instance." + a directory delimiter and returns a new fileName instance. + See also: #withSuffix: which is new and better." ^ (nameString , aString asString) " - 'Makefile' asFilename , '.bak' - 'Makefile' asFilename construct:'.bak' + 'Makefile' asFilename , '.bak' + ('Makefile' asFilename , '.bak') asFilename + 'Makefile' asFilename withSuffix:'bak' + 'Makefile' asFilename construct:'.bak' " + + "Modified: 29.2.1996 / 20:54:12 / cg" ! ! !Filename methodsFor:'printing & storing'! @@ -1160,23 +1247,6 @@ !Filename methodsFor:'queries'! -baseName - "return my baseName as a string. - - thats the file/directory name without leading parent-dirs." - - ^ OperatingSystem baseNameOf:nameString "/ (self pathName) - - " - '/foo/bar' asFilename baseName - '.' asFilename baseName - '..' asFilename baseName - '../..' asFilename baseName - '../../libbasic' asFilename baseName - '../../libpr' asFilename baseName - '../../libbasic/Object.st' asFilename baseName - " -! - canBeWritten "same as isWritable - for ST-80 compatibility" @@ -1189,72 +1259,6 @@ " ! -directory - "return the directory name part of the file/directory as a filename. - - thats a filename for the directory where the file/dir represented by - the receiver is contained in." - - ^ self directoryName asFilename - - " - '/foo/bar' asFilename directory - '.' asFilename directory - '..' asFilename directory - '../..' asFilename directory - " -! - -directoryContents - "return the contents of the directory as a collection of strings" - - ^ (FileDirectory directoryNamed:self asString) contents - - " - '.' asFilename directoryContents - " -! - -directoryName - "return the directory name part of the file/directory as a string. - - thats the name of the directory where the file/dir represented by - the receiver is contained in. - See also: #directoryPathName" - - ^ OperatingSystem directoryNameOf:nameString "/ (self pathName) - - " - '/foo/bar/' asFilename directoryName - '/foo/bar' asFilename directoryName - 'bitmaps' asFilename directoryName - 'bitmaps' asFilename directoryPathName - '.' asFilename directoryName - '..' asFilename directoryName - '../..' asFilename directoryName - '../..' asFilename directoryPathName - " - - "Modified: 7.9.1995 / 10:42:03 / claus" -! - -directoryPathName - "return the full directory pathname part of the file/directory as a string. - - thats the full pathname of the directory where the file/dir represented by - the receiver is contained in. - See also: directoryName" - - ^ OperatingSystem directoryNameOf:(self pathName) - - " - '/foo/bar/' asFilename directoryPathName - '/foo/bar' asFilename directoryPathName - '.' asFilename directoryPathName - '..' asFilename directoryPathName - '../..' asFilename directoryPathName - " - - "Modified: 7.9.1995 / 10:42:13 / claus" -! - exists "return true, if such a file exists." @@ -1267,155 +1271,6 @@ " ! -filenameCompletion - "try to complete the recevier filename. - This method has both a return value and a side effect on the receiver: - it returns a collection of matching filename objects, - and leaves changes the receivers filename-string to the longest common - match. - If none matches, the returned collection is empty and the recevier is unchanged. - If there is only one match, the size of the returned collection is exactly 1, - containing the fully expanded filename and the receivers name is changed to it." - - ^ self filenameCompletionIn:nil - - " - 'mak' asFilename filenameCompletion - 'Make' asFilename filenameCompletion - 'Makef' asFilename filenameCompletion;yourself - '/u' asFilename filenameCompletion - '../../libpr' asFilename inspect filenameCompletion - " -! - -filenameCompletionIn:aDirectory - "try to complete the recevier filename. - This method has both a return value and a side effect on the receiver: - it returns a collection of matching filename objects, - and leaves changes the receivers filename-string to the longest common - match. - If none matches, the returned collection is empty and the recevier is unchanged. - If there is only one match, the size of the returned collection is exactly 1, - containing the fully expanded filename and the receivers name is changed to it." - - |dir baseName matching matchLen try allMatching - sepString parentString prefix nMatch| - - sepString := self class separator asString. - (nameString endsWith:sepString) ifTrue:[ - ^ #() - ]. - - parentString := self class parentDirectoryName. - baseName := self baseName. - baseName ~= nameString ifTrue:[ - prefix := self directoryName. - ]. - - self isAbsolute ifTrue:[ - dir := self directory - ] ifFalse:[ - aDirectory isNil ifTrue:[ - dir := self directory - ] ifFalse:[ - dir := (aDirectory construct:nameString) directory - ] - ]. - - matching := OrderedCollection new. - dir directoryContents do:[:fileName | - ((fileName ~= '.') and:[fileName ~= parentString]) ifTrue:[ - (fileName startsWith:baseName) ifTrue:[ - matching add:fileName - ] - ] - ]. - (nMatch := matching size) > 1 ifTrue:[ - " - find the longest common prefix - " - matchLen := baseName size. - matchLen > matching first size ifTrue:[ - try := baseName. - allMatching := false - ] ifFalse:[ - try := matching first copyTo:matchLen. - allMatching := true. - ]. - - [allMatching] whileTrue:[ - matching do:[:aName | - (aName startsWith:try) ifFalse:[ - allMatching := false - ] - ]. - allMatching ifTrue:[ - matchLen < matching first size ifTrue:[ - matchLen := matchLen + 1. - try := matching first copyTo:matchLen. - ] ifFalse:[ - allMatching := false - ] - ] ifFalse:[ - try := matching first copyTo:matchLen - 1. - ] - ]. - " - and set my name to the last full match - " - nameString := try - ]. - - " - if I had a directory-prefix, change names in collection ... - " - prefix notNil ifTrue:[ - prefix = '/' ifTrue:[ - "/ avoid introducing double slashes - prefix := '' - ]. - matching := matching collect:[:n | prefix , '/' , n]. - nMatch == 1 ifTrue:[ - nameString := matching first - ] ifFalse:[ - nMatch > 1 ifTrue:[ - nameString := prefix , '/' , nameString - ] - ] - ] ifFalse:[ - nMatch == 1 ifTrue:[ - nameString := matching first - ] - ]. - - " - return the match-set, so caller can decide what to do - (i.e. show the matches, output a warning etc ...) - " - ^ matching - - " trivial cases: - - '../' asFilename filenameCompletion - '/' asFilename filenameCompletion - '/usr/' asFilename filenameCompletion - - 'mak' asFilename filenameCompletion - 'Make' asFilename filenameCompletion - 'Makef' asFilename filenameCompletion - '/u' asFilename filenameCompletion - '../../libpr' asFilename filenameCompletion - " -! - -filesMatching:aPattern - ^ self directoryContents select:[:name | aPattern match:name] - - " - Filename currentDirectory filesMatching:'M*' - " -! - isAbsolute "return true, if the receiver represents an absolute pathname (in contrast to one relative to the current directory)." @@ -1517,6 +1372,311 @@ " ! +separator + "return the directory-separator character" + + ^ self class separator + + "Modified: 29.2.1996 / 20:52:01 / cg" +! ! + +!Filename methodsFor:'queries-contents'! + +contentsOfEntireFile + "return the contents of the file as a string" + + |s contents| + + s := self readStream. + [ + contents := s contents + ] valueNowOrOnUnwindDo:[s close]. + ^ contents +! + +directoryContents + "return the contents of the directory as a collection of strings" + + ^ (FileDirectory directoryNamed:self asString) contents + + " + '.' asFilename directoryContents + " +! + +filesMatching:aPattern + "given the receiver, representing a directory; + return a collection of files matching a pattern." + + ^ self directoryContents select:[:name | aPattern match:name] + + " + Filename currentDirectory filesMatching:'M*' + '/etc' asFilename filesMatching:'[a-z]*' + '../../libbasic' asFilename filesMatching:'[A-D]*.st' + " + + "Modified: 29.2.1996 / 20:30:31 / cg" +! ! + +!Filename methodsFor:'queries-path & name'! + +baseName + "return my baseName as a string. + - thats the file/directory name without leading parent-dirs." + + ^ OperatingSystem baseNameOf:nameString "/ (self pathName) + + " + '/foo/bar' asFilename baseName + '.' asFilename baseName + '..' asFilename baseName + '../..' asFilename baseName + '../../libbasic' asFilename baseName + '../../libpr' asFilename baseName + '../../libbasic/Object.st' asFilename baseName + " +! + +directory + "return the directory name part of the file/directory as a new filename. + - thats a filename for the directory where the file/dir represented by + the receiver is contained in. + (this is almost equivalent to #directoryName or #head, but returns + a Filename instance instead of a string )." + + ^ self directoryName asFilename + + " + '/foo/bar' asFilename directory + '/foo/bar' asFilename directoryName + '/foo/bar' asFilename head + + '.' asFilename directory + '..' asFilename directory + '../..' asFilename directory + " + + "Modified: 29.2.1996 / 20:50:14 / cg" +! + +directoryName + "return the directory name part of the file/directory as a string. + - thats the name of the directory where the file/dir represented by + the receiver is contained in. + (this is almost equivalent to #directory, but returns + a string instead of a Filename instance). + See also: #directoryPathName. + Compatibility note: use #head for ST-80 compatibility." + + ^ OperatingSystem directoryNameOf:nameString "/ (self pathName) + + " + '/foo/bar/' asFilename directoryName + '/foo/bar/' asFilename directory + + '/foo/bar' asFilename directoryName + 'bitmaps' asFilename directoryName + 'bitmaps' asFilename directoryPathName + '.' asFilename directoryName + '..' asFilename directoryName + '../..' asFilename directoryName + '../..' asFilename directoryPathName + " + + "Modified: 7.9.1995 / 10:42:03 / claus" + "Modified: 29.2.1996 / 20:23:49 / cg" +! + +directoryPathName + "return the full directory pathname part of the file/directory as a string. + - thats the full pathname of the directory where the file/dir represented by + the receiver is contained in. + See also: #directoryName, #directory" + + ^ OperatingSystem directoryNameOf:(self pathName) + + " + '/foo/bar/' asFilename directoryPathName + '/foo/bar' asFilename directoryPathName + + '.' asFilename directoryPathName + '.' asFilename directoryName + '.' asFilename directory + + '..' asFilename directoryPathName + '..' asFilename directoryName + '..' asFilename directory + + '../..' asFilename directoryPathName + " + + "Modified: 7.9.1995 / 10:42:13 / claus" + "Modified: 29.2.1996 / 20:24:44 / cg" +! + +filenameCompletion + "try to complete the receiver filename. + This method has both a return value and a side effect on the receiver: + it returns a collection of matching filename objects, + and leaves changes the receivers filename-string to the longest common + match. + If none matches, the returned collection is empty and the recevier is unchanged. + If there is only one match, the size of the returned collection is exactly 1, + containing the fully expanded filename and the receivers name is changed to it." + + ^ self filenameCompletionIn:nil + + " + 'mak' asFilename filenameCompletion + 'Make' asFilename filenameCompletion + 'Makef' asFilename filenameCompletion;yourself + '/u' asFilename filenameCompletion + '../../libpr' asFilename inspect filenameCompletion + " + + "Modified: 29.2.1996 / 20:28:36 / cg" +! + +filenameCompletionIn:aDirectory + "try to complete the receiver filename. + This method has both a return value and a side effect on the receiver: + it returns a collection of matching filename objects, + and leaves changes the receivers filename-string to the longest common + match. + If none matches, the returned collection is empty and the recevier is unchanged. + If there is only one match, the size of the returned collection is exactly 1, + containing the fully expanded filename and the receivers name is changed to it." + + |dir baseName matching matchLen try allMatching + sepString parentString prefix nMatch| + + sepString := self class separator asString. + (nameString endsWith:sepString) ifTrue:[ + ^ #() + ]. + + parentString := self class parentDirectoryName. + baseName := self baseName. + baseName ~= nameString ifTrue:[ + prefix := self directoryName. + ]. + + self isAbsolute ifTrue:[ + dir := self directory + ] ifFalse:[ + aDirectory isNil ifTrue:[ + dir := self directory + ] ifFalse:[ + dir := (aDirectory construct:nameString) directory + ] + ]. + + matching := OrderedCollection new. + dir directoryContents do:[:fileName | + ((fileName ~= '.') and:[fileName ~= parentString]) ifTrue:[ + (fileName startsWith:baseName) ifTrue:[ + matching add:fileName + ] + ] + ]. + (nMatch := matching size) > 1 ifTrue:[ + " + find the longest common prefix + " + matchLen := baseName size. + matchLen > matching first size ifTrue:[ + try := baseName. + allMatching := false + ] ifFalse:[ + try := matching first copyTo:matchLen. + allMatching := true. + ]. + + [allMatching] whileTrue:[ + matching do:[:aName | + (aName startsWith:try) ifFalse:[ + allMatching := false + ] + ]. + allMatching ifTrue:[ + matchLen < matching first size ifTrue:[ + matchLen := matchLen + 1. + try := matching first copyTo:matchLen. + ] ifFalse:[ + allMatching := false + ] + ] ifFalse:[ + try := matching first copyTo:matchLen - 1. + ] + ]. + " + and set my name to the last full match + " + nameString := try + ]. + + " + if I had a directory-prefix, change names in collection ... + " + prefix notNil ifTrue:[ + prefix = '/' ifTrue:[ + "/ avoid introducing double slashes + prefix := '' + ]. + matching := matching collect:[:n | prefix , '/' , n]. + nMatch == 1 ifTrue:[ + nameString := matching first + ] ifFalse:[ + nMatch > 1 ifTrue:[ + nameString := prefix , '/' , nameString + ] + ] + ] ifFalse:[ + nMatch == 1 ifTrue:[ + nameString := matching first + ] + ]. + + " + return the match-set, so caller can decide what to do + (i.e. show the matches, output a warning etc ...) + " + ^ matching + + " trivial cases: + + '../' asFilename filenameCompletion + '/' asFilename filenameCompletion + '/usr/' asFilename filenameCompletion + + 'mak' asFilename filenameCompletion + 'Make' asFilename filenameCompletion + 'Makef' asFilename filenameCompletion + '/u' asFilename filenameCompletion + '../../libpr' asFilename filenameCompletion + " + + "Modified: 29.2.1996 / 20:28:45 / cg" +! + +head + "return the directory name as a string. + An alias for directoryName, for ST-80 compatiblity. + (this is almost equivalent to #directory, but returns + a string instead of a Filename instance)" + + ^ self directoryName + + " + Filename currentDirectory head + 'Makefile' asFilename head + '/foo/bar/baz.st' asFilename head + " + + "Modified: 29.2.1996 / 20:21:25 / cg" +! + name "return the name of the file represented by the receiver as a string. This may or may not be a relative name (i.e. include ..'s). @@ -1571,46 +1731,6 @@ "Modified: 18.1.1996 / 21:36:46 / cg" ! -prefixAndSuffix - "return an array consisting of my prefix and suffix. - The suffix is the namepart after the final period character, - the prefix everything before, except for the period. - (on some systems, the suffix-character may be different from a period). - For example, foo.bar.baz has a prefix of 'foo.bar' and a suffix of '.baz'. - - Notice: there is currently no known system which uses other than - the period character as suffixCharacter." - - |nm idx| - - nm := self baseName. - idx := nm lastIndexOf:(self class suffixSeparator). - idx == 0 ifTrue:[ - ^ Array with:nm with:'' - ]. - ^ Array - with:(nm copyTo:idx-1) - with:(nm copyFrom:idx+1) - - " - 'abc.st' asFilename prefixAndSuffix - 'abc' asFilename prefixAndSuffix - 'a.b.c' asFilename prefixAndSuffix - - |parts| - parts := 'Object.st' asFilename prefixAndSuffix. - ((parts at:1) , '.o') asFilename - " - - "Modified: 7.9.1995 / 11:15:42 / claus" -! - -separator - "return the directory-separator character (or string)" - - ^ self class separator -! - suffix "return my suffix. The suffix is the namepart after the final period character, @@ -1632,10 +1752,98 @@ An alias for baseName, for ST-80 compatiblity." ^ self baseName + + " + Filename currentDirectory tail + 'Makefile' asFilename tail + '/foo/bar/baz.st' asFilename tail + " + + "Modified: 29.2.1996 / 20:19:50 / cg" +! ! + +!Filename methodsFor:'suffixes'! + +prefixAndSuffix + "return an array consisting of my prefix and suffix. + The suffix is the namepart after the final period character, + the prefix everything before, except for the period. + (on some systems, the suffix-character may be different from a period). + For example, foo.bar.baz has a prefix of 'foo.bar' and a suffix of '.baz'. + + Notice: there is currently no known system which uses other than + the period character as suffixCharacter." + + |nm idx| + + nm := self baseName. + idx := nm lastIndexOf:(self class suffixSeparator). + idx == 0 ifTrue:[ + ^ Array with:nm with:'' + ]. + ^ Array + with:(nm copyTo:idx-1) + with:(nm copyFrom:idx+1) + + " + 'abc.st' asFilename prefixAndSuffix + 'abc' asFilename prefixAndSuffix + 'a.b.c' asFilename prefixAndSuffix + + |parts| + parts := 'Object.st' asFilename prefixAndSuffix. + ((parts at:1) , '.o') asFilename + " + + "Modified: 7.9.1995 / 11:15:42 / claus" +! + +withSuffix:aSuffix + "return a new filename for the receivers name with a suffix. + If the name already has a sufix, the new suffix replacaes it; + otherwise, the new suffix simply appended to the name." + + ^ self class named: + (self withoutSuffix name + , self class suffixSeparator asString + , aSuffix asString) + + " + 'abc.st' asFilename withSuffix:'o' + 'abc' asFilename withSuffix:'o' + 'a.b.c' asFilename withSuffix:'o' + '/foo/bar/baz.st' asFilename withSuffix:'c' + '/foo/bar/baz.c' asFilename withSuffix:'st' + " + + "Modified: 7.9.1995 / 11:15:42 / claus" + "Modified: 29.2.1996 / 20:50:03 / cg" +! + +withoutSuffix + "return a new filename for the receivers name without the suffix. + If the name has no suffix, the receiver is returned." + + |idx| + + idx := nameString lastIndexOf:(self class suffixSeparator). + idx == 0 ifTrue:[^ self]. + + ^ self class named:(nameString copyTo:(idx - 1)) + + " + 'abc.st' asFilename withoutSuffix + 'abc' asFilename withoutSuffix + 'a.b.c' asFilename withoutSuffix + '/foo/bar/baz.c' asFilename withoutSuffix + " + + "Modified: 7.9.1995 / 11:15:42 / claus" + "Modified: 29.2.1996 / 20:49:59 / cg" ! ! !Filename class methodsFor:'documentation'! version - ^ '$Header: /cvs/stx/stx/libbasic/Filename.st,v 1.50 1996-02-04 19:06:34 cg Exp $' + ^ '$Header: /cvs/stx/stx/libbasic/Filename.st,v 1.51 1996-02-29 20:01:28 cg Exp $' ! !