Re: Type/Creator codes
Re: Type/Creator codes
- Subject: Re: Type/Creator codes
- From: John Hörnkvist <email@hidden>
- Date: Mon, 14 May 2001 00:09:31 +0200
On Sunday, May 13, 2001, at 02:56 AM, Ali Ozer wrote:
I can't seem to find any cocoa API for setting Type/Creator codes on
files you create. Does anyone know of any?
...
Since the source for TextEdit comes with the developer CD, I thought I
might "fix" it so that it saves files with type/creator codes TEXT/text
which TextEdit seems to work with. Maybe make the .rtf/.txt optional
in preferences. Not sure what to do with .rtfd since really the finder
should hide that like it does for .app.
There is indeed a need to save type/creator codes in some cases, even
from Cocoa apps. For instance, if you want to generate documents which
work properly on Mac OS 9.
However, for many new apps, and for documents that don't need to be
opened on 9, you should not have to set types or creator codes; file
extensions by themselves should be enough.
Of course one downside of file extensions is the fact that they are in
the user's face, and they are fragile. However, 10.0 is not the final
word on how extensions will work on Mac OS X. We are looking at ways to
enhance things such that the user experience of file extensions is at
least as good as the user experience of Mac OS file types on Mac OS 9,
while retaining the advantages of file extensions --- the fact that they
are web-friendly and cross-platform. More on this later. (By that I
don't mean later today!)
Since this topic is recurring, I thought I'd save some time by quoting a
mail from me to email@hidden in February last year and
Bruce Horn's reply to it --- IIRC he worked on the original Mac OS and
Finder, which makes his point of view particularly interesting,
Here is my post:
>>>
Kristoffer Peterhansel wrote:
> on 09/02/2000 18:15, email@hidden at email@hidden wrote:
>
> > Ivan C Myrvold wrote:
> >> When I want to change a filetype or file creator, I drag the file to
> >> FileTyper which I have on my desktop, and change either the filetype
> >> field or filecreator field, and hit OK. A very simple twostep
> >> operation.
> >
> > This works fine in a single user environment -- although I don't
think it
> > should require extra tools -- but not so great if it is a shared
file in
> > a multi user environment.
>
> Isn't it great to just be able to say "it won't work in a multi user
> environment".
I said it won't work well in a multi user environment, not that it will
not
work in a multi user environment.
> And that's that? WHY won't it work? What's so problematic?
The problem is that if you use the current semantics of creators,
combined
with file ownership, a user may not be allowed to change the creator of a
file. Thus, the user would always have to use drag and drop with that
file in
order to avoid opening it in the wrong application. [Imagine that you're
managing a group of graphics artists. These create a lot of images from
Photoshop. For the sake of economics, there is no Photoshop on your
machine,
and you just want to look at the files. In that case, the usual user
interface action of double clicking would cause the wrong behaviour, and
the
manager could not change it without disturbing the artists.]
Creator, as "default application for this particular file to open in",
should not be a mapping (file -> application) but ((file,user) ->
application), and possible even ((file,user,mode) -> application), with
the
default case ((type,user) -> application).
One could solve this by doing away with creator types, and using a per
file
database in the file system instead. (Like an ACL, but with
user->application
mappings instead.) However, this system would not work well in a
heterogenous network.
Another solution would be to have a per user database of (file ->
application) mappings, in addition to the existing (type -> application).
However, this mapping would be fragile; if the files reside on an NFS
server
(running, say Linux), and are moved at that location, the mapping would
break. If the file is owned by another user, and that user moves the
file,
the mapping breaks. [Unless the system checks for associations to the
file
made by other users and notifies or updates. This would work in a small
system, but would be costly in a system with many users.]
> Sure you mention later on in your mail that in *step every user have
it's
> own file extension mappings. But that don't really have anything to do
with
> where the file type is identified. And then you say something about we
> could have two extensions so the creator is stored too. WHY?!?!
Because it is simple to do. If some users want creator info, it is
trivial
to implement, without changing the file system. Why does it matter to you
where the information is stored, if the semantics are the same? There
is a
clear advantage to putting file type information in the file name, since
all
modern file systems support named files. I do not like the semantics of
the
creator system, as it is now, though.
I must point out that there are cases when a type only mapping isn't
sufficient; on NeXTSTEP it happened mostly with textfiles. You sometimes
get
a new file type (Haskell source, .hs and .lhs, for example), and while
this
file is a textfile, it requires its extension to be used with the Unix
part
of the system. Often Emacs has a special mode for such files, and you
want to
edit it there. However, Emacs doesn't inform the system that it can
handle
those files, so you can't select Emacs and set it as the default
application
in the Inspector. You can make Emacs the default by editing the right
file in
.NeXT, or by doing a dwrite to make Emacs the default app rather than
Edit,
but that isn't very user friendly.
Since Edit.app was registered as being able to open all file types, there
was normally an easy way to handle that. Drag and drop is always a
workaround, but it disturbs the workflow.
_THE PROBLEM WITH FILETYPE -> APPLICATION MAPPING_
There are cases when the relation between file and type is not one to
one.
Example: A Haskell source file can be edited with any text editor -- it
is
of the TEXT type. However, the haskell interpreter and compiler works
only on
a subset of all text files, they work on text files in the Haskell
syntax.
Thus, the file should be of the HASKELL type. But if it is of the HASKELL
type, text editors registered for the TEXT type will not known that they
can
edit it.
_A SOLUTION USING TYPE CLASSES_
Example:
Assume that the Haskell compiler handles data of the type (Haskell.Text),
which is a subclass of Text.
Each application registers the type transformations (injection,
projection)
that it can handle.
An imaginary application "TextEdit" has the mapping (inj :: Text ->
RichText, prj :: RichText -> Maybe Text). (Projection may fail.)
So, when the File Manager sees a file f of the type (Haskell.RichText),
it
can infer that (prj :: Haskell.RichText -> Haskell.Text), thus making the
Haskell compiler one of the options of opening any file
(Haskell.RichText).
By making clear that the conversion is a projection, the type system
knows
that the conversion can be lossy, and should be treated as such -- if
there
is an application that handles the type (Haskell.RichText) natively, it
should have higher preference as a default.
We can do the same thing more deeply, with something like
(LiterateHaskell.Html.Text).
Description:
An application that can convert data from one format to another
registers an
injection function (inj :: TypeA -> TypeB) or a projection function
(prj ::
TypeA -> Maybe TypeB). An injection is a lossless conversion, whereas a
projection is a lossy conversion which is not guaranteed to succeed.
A file type is of the form (recursively defined):
Filetype = Type
| Filetype.Type
A Type t may only occur once in a FileType. (I.e. Text.Text.Text is not
allowed.)
Type relationships can be inferred from the injection and projection
mappings, in one or more steps. Injection mappings are always given
preference over projections. (I.e. RichText -> PostScript -> PDF chosen
over
RichText -> Text -> PDF)
Comparison between types; types form a partial ordering.
This means that
compare Haskell Text = Nothing
compare Text Text = Equal
compare Text Haskell.Text = Greater {-Haskell.Text is a subtype of
Text-}
compare Haskell.Text Text = Less
An application is eligible for opening a file if the application has any
complete type that is greater than or equal to the type of the file, or
to a
projection/injection of the file type.
By using this system, one can overcome many of the limitations of a the
traditional (type -> application) mappings (I think it is similar to how
NEXTSTEP handles the pasteboard), and allow richer semantics for user
preferences than in current systems.
Presenting this type information to the user is likely best done by
hiding
it as default -- displaying it in the inspector -- and simply using the
correct icon. Combine it with a per user database of (file ->
application)
associations, and it should work pretty well.
Note that a jpeg file does not have the type JPEG.Image in this scheme,
but
the type JPEG. The type system will infer that it is an "image" if there
is a
mapping to the systems default image format (TIFF, for example), i.e. an
application or service that does (inj :: JPEG -> TIFF) or (prj :: JPEG ->
TIFF)
> Then we are back to what you are arguing against: The user wants to
define
> what apps open what types of files.
This is not what I'm arguing against. This is what I'm arguing for. I'm
saying that creator codes is a silly way of doing it in a world of
heterogenous networks.
Using creator/type codes implemented in the file system, or using file
name
extensions give similar expressiveness. Indeed, either can be made to
emulate
the other. However, both forms are overly limited, and only file name
extensions interacts well with heterogenous networks.
>>> Irrelevant part removed <<<
<<<
And here is Bruce's reply:
>>>
>John Hornkvist wrote:
>...stuff deleted
>Creator, as "default application for this particular file to open in",
>should not be a mapping (file -> application) but ((file,user) ->
>application), and possible even ((file,user,mode) -> application), with
the
>default case ((type,user) -> application).
Absolutely. Most of us aren't saying that a type/creator pair is the
ultimate solution, just that many of the other solutions being offered
are no better, and in some ways much worse.
>_THE PROBLEM WITH FILETYPE -> APPLICATION MAPPING_
>..
>_A SOLUTION USING TYPE CLASSES_
>Example:
>Assume that the Haskell compiler handles data of the type
(Haskell.Text),
>which is a subclass of Text.
>
>Each application registers the type transformations (injection,
projection)
>that it can handle.
>
>An imaginary application "TextEdit" has the mapping (inj :: Text ->
>RichText, prj :: RichText -> Maybe Text). (Projection may fail.)
>
>So, when the File Manager sees a file f of the type (Haskell.RichText),
it
>can infer that (prj :: Haskell.RichText -> Haskell.Text), thus making
the
>Haskell compiler one of the options of opening any file
(Haskell.RichText).
>By making clear that the conversion is a projection, the type system
knows
>that the conversion can be lossy, and should be treated as such -- if
there
>is an application that handles the type (Haskell.RichText) natively, it
>should have higher preference as a default.
>
>We can do the same thing more deeply, with something like
>(LiterateHaskell.Html.Text).
>
This is very much like the type hierarchy I was proposing to replace
types/creators over 15 years ago, but I ended up leaving Apple before I
could implement it. We had the desktop database and could have easily
done this.
John: Excellent, thoughtful post. I would be happy with such a system.
Implement it!
>>> Irrelevant part removed <<<
Bruce Horn
<<<
To prove that this form of extensions, projections and all works, I did
implement the project/injection part.
A more nicely formatted version of the above can be found at
http://www.toastedmarshmallow.com/Articles/TypingFiles2.pdf.
Regards,
John Hornkvist
--
ToastedMarshmallow, the perfect Cocoa companion
http://www.toastedmarshmallow.com