And while I'm on that subject. It looks to me like lil' ol' BeIDE does
a better job of file handling that gigantic ol' Project Builder. After
a bit of tinkering I discovered BeIDE only needed two paths added to
each project, the top-level common TropicLib source directory and the
top-level BeOS port directory. Meanwhile, Project Builder gives me two
choices, neither very appealing. One, I can add every single include
directory to the project. I don't get that at all. BeIDE only needs a
top-level directory added, it will recurse into subdirs to find headers
and source files, but Project Builder will not. Despite the fact that
both IDEs are using gcc. What the heck? I guess BeIDE is manually
iterating through subdirs and turning them all into -I arguments for gcc
but Project Builder isn't.
So I added all the include subdirs to Project Builder. But I discovered
something bad. The IDE's text editor window has a small button that
means "find this module's other half." So if you're editing Thing.cpp,
pressing that button will open Thing.h for you. Except it doesn't work
unless the .h file you're looking for is explicitly added to the
project. Auuugh. So that's the less appealing second option: don't add
include subdirs, add every single .h file instead. Which I had to do
because I *need* that "find this module's other half" button. BeIDE's
text editor is able to provide a button that pops up a menu of *all*
included .h files, not just the current file's other half, without you
having to add header files to the project.
And then I virtualized my very first module. I picked a small and
simple one because I'm worried this could turn out disastrous. My
character set conversion module is tiny, there are only three
platform-specific functions. So the CSet module got ripped into three
pieces, sprouting a new CSetImp for BeOS and another for MacOSX.
Nothing major, but it *was* nice to remove all those #ifdefs.
Man, this will be just the thing for finishing my text input control.
It's already monstrous and I've only got it working on BeOS. The idea
that I will be able to split it into three smaller, less complicated
modules lessens my stress level a lot.
So now there is an obvious and perfect spot for ALEX G.M. SMITH,
PROGRAMMER-OF-THE-NORTH, to add a Windows directory to the TropicLib
source tree and start filling in the blanks. Then perhaps he can write
his own progress updates like this one. Here's a suggested first entry:
Dear diary,
Today I made the world safe for convicted monopolists.
HA HA! I just get FUNNIER AND FUNNIER ALL THE TIME!
The annoying thing is that it might actually make money, if Pineapple
becomes better than Outlook Express (which it seems to look like for
some reason) or the other news readers. The downside, besides coding
annoyances, is that I'd have to deal with Windows users.
- Alex
Because that's what I was using before I wrote PNews, of course. I
honestly tried to think of a better metaphor than the three-pane main
window but nothing came to me.
I am still open to ideas, if anybody's got one that makes any sense.
Since I've re-factored my GUI code into nice building blocks it probably
wouldn't be very hard to reconfigure them into an entirely different
interface altogether. I could even have two or more interface paradigms
supported in the same executable, most likely.
> The downside, besides coding annoyances, is that I'd have to deal
> with Windows users.
Oddly enough, that's the *least* of my worries.
Yes, there are stupid Windows users. On the other hand, I should let
you peek at my saved folder full of PNews support e-mail. Hoo boy.
Don't let anybody tell you Windows has a monopoly on stupid users.
It's just a matter of numbers, I think. I'm sure I got at least a
thousand e-mails about PNews in the first two months of release.
There's no way in hell they could *all* be reasoned and thoughtful.
That was one thing cool about releasing the first version of my
newsreader as a total not-for-profit venture: whenever I got an e-mail
that was too stupid for words I was free to ignore it. Most of which I
did.
I'd like to do it as a BeMail style system. An editor / reader program
to work on individual messages. A separate threading mechanism in
OpenTracker to select messages (means adding a tree view to OpenTracker
and threading through an attribute - like message ID, and adding Tracker
scripting messages for moving the selection up, down, left, right
(already has up and down)).
Again, the idea is to mix news messages, e-mail messages, word
processing documents and other things all in one directory (usually the
user will have a topic for each directory).
- Alex
Okay, I'll go that far. Then ...
> A separate threading mechanism in OpenTracker to select messages
> (means adding a tree view to OpenTracker and threading through an
> attribute - like message ID, and adding Tracker scripting messages
> for moving the selection up, down, left, right (already has up
> and down)).
DHUDE! No WAY am I committing to doing THAT.
Tell you what. You write the OpenTracker threading parts, and when you
get underway on that one I'll commit to adding PNews support, which
would mean writing three separate applets to make it work: the
posting/retrieving engine, a message viewer, and a message editor. I
was already going to write the message viewer anyway. It would also
mean adding the References: header as an attribute on every message so
you could use it for threading.
WARNING WARNING DANGER WARNING ERROR The PNews header view is far and
away the most complicated part of the program. By like an order of
magnitude. It's a LOT harder than it looks. Basically you'd get to
duplicate that in OpenTracker.
First big stumbling block: BOutlineListView is a steaming pile of poop.
It's very poorly designed and starts to break down when you try to add
thousands and thousands of entries.
Did you know that BOutlineListView came up in my job interview at Be?
Yep. One of the best questions they asked me, which I thought was very
insightful and flattering and everything. I can't even remember which
one of the three it was that asked, but it went like this:
BE PERSON: It would seem that there's an enormous amount of code in your
newsreader.
JOHNNY FAVORITE: Oh, man. Like you wouldn't believe. If I'd known how
long it would take I might never have started.
BP: What would you say was the biggest encumbrance BeOS placed on you
getting it finished?
JF: BOutlineListView. No question about it.
Then I went on to admit that I'd cheated. BOLV has a method that will
let you add a BList of items. It is very very very fast compared to
adding them all individually. The problem is that there is no way to
thread those items. They must all be top-level. The 'fLevel' data
member of BListItem is private and unaccessible to civilians such as
myself. So I cheated and edited ListItem.h to make the member protected
instead of private.
Along about BeOS version 5.0.2 the binary layout of BListItem changed,
breaking my cheat. When I said that, Dianne Hackborn's eyebrows went
up. She knew exactly what I was talking about. We had been discussing
that on c.s.b.p and I wouldn't be surprised if she changed the binary
layout simply to foil my hack. But I poked around inside the object,
found the new offset, and started using it there. I even added a test
at the beginning of the program to figure out where it was so PNews
would work on older and newer versions of BeOS.
Wow! You can't believe how incensed they were that I was going behind
their back like that! Like I murdered their puppies or something!
I really *wanted* to play by the rules, but it just wasn't possible. I
had a test folder of 10,000 messages. Adding them to a BOLV the legal
way, one at a time, and threading them afterwards, took over a minute.
Adding them all to a BList, threading them "illegally," and sticking
them in at once was instantaneous. After I explained that, none of them
had anything further to say about it. They knew I had made the right
design decision. And you notice I got the job.
So, should you try to duplicate all that in OpenTracker, you probably
would want to use the replacement BOutlineListView I eventually wrote,
which gets around that problem as well as a few others. Rotsa ruck,
pal!
So while we're on the subject. I seem to recall you writing a BeIDE
add-on for some purpose or the other. Well, I have apparently finally
gotten the following equations through my thick head:
Function-level comments before the function body = GOOD
Module-level comments in the header file = BETTER
End-of-line comments = BAD
Function-level comments that make cool pop culture references to trendy
people like Ellen Feiss while simultaneously disparaging Windows = BEST
The problem is that I've got eighty TRILLION end-of-line comments I need
to get rid of. I can't just scrape them *all* out via some automated
means because about one out of a thousand contains some kind of useful
information, and I plan to keep the ones that delineate the beginning
and end of functions.
I'm making myself take them out as I refurbish and virtualize my old
modules and I swear, my typing fingers are getting NUMB from removing
thousands and thousands and THOUSANDS of my stupid pointless comments
like "Set new value" and "Copy caller's string" and other blatantly
OBVIOUS stuff that never should have been commented in the first place.
No kidding, I'm sure I've spent at least ten hours backspacing over the
dratted things and I'm nowhere near halfway done.
So how hard would it be to write a BeIDE editor add-on that
A) is activated by a hotkey
B) goes to the end of the line containing the cursor
C) backspaces until it hits //, then removes the //
D) keeps backspacing to eliminate trailing whitespace
E) locates Ellen-Feiss-related comments, makes them BOLD and BLINKING
Because if it is possible and takes me less than 20 hours to write, it
would be a net win. BEEP BEEP BEEP BEEP BEEP BEEP BEEP BEEP.
Sounds good to me. Perhaps Axel will do the OpenTracker tree view,
which got mentioned a while ago on the OT mailing list. Just needs a
more flexible way of finding children / parent of a thing. But then
he's pretty busy with OpenBeOS. Or I could tackle it.
Another alternative I've thought of - an NNTP file system. Represent
the messages as directories containing their replies, with a
MessageText.txt fake file (or an attribute on the directory) for the
message's text. I just keep on running into that annoying 1970's
file/directory technology, I want fildirutes now! Maybe something for
my next user level generic file system framework to do, as well as FTP,
HTTP, Zip files, etc.
> First big stumbling block: BOutlineListView is a steaming pile of
> poop.
Maybe just ignore the Be classes and write a new one, or borrow one from
somewhere on BeBits. Or borrow yours.
> Did you know that BOutlineListView came up in my job interview at Be?
Cool story!
> So, should you try to duplicate all that in OpenTracker, you probably
> would want to use the replacement BOutlineListView I eventually wrote,
> which gets around that problem as well as a few others. Rotsa ruck,
> pal!
Heh.
> So while we're on the subject. I seem to recall you writing a BeIDE
> add-on for some purpose or the other.
A word wrapper, so I can insert text into my ultra verbose comments and
rewrap and space the words out to make it look nice.
> Function-level comments before the function body = GOOD
Yup.
> Module-level comments in the header file = BETTER
Nope. I've given up on header files as being useless. It's all too
easy for comments there to get out of sync with comments in the source
code, or just never get updated. I put the comments in the source and
minimal commenting in the header (just explaining the data types which
have to be in the headers).
> End-of-line comments = BAD
Rarely used here too.
> Function-level comments that make cool pop culture references to
> trendy people like Ellen Feiss while simultaneously disparaging
> Windows = BEST
If you say so. I also like large module level comments explaining how
the whole thing fits together. And research paths explored, so that
people will know what ideas have been looked at and rejected as being
stupid. Kind of like your rants, but in the source code.
> The problem is that I've got eighty TRILLION end-of-line comments I
> need to get rid of. I can't just scrape them *all* out via some
> automated means because about one out of a thousand contains some kind
> of useful information, and I plan to keep the ones that delineate the
> beginning and end of functions.
BeIDE find's regex not good enough? Search for "[ \t]*//.*$" (without
the quote marks) and replace with "". It's interactive too, hit ALT-G
to find the next one, replace it with the nothing by using ALT-L, or if
you want to keep it, just use another ALT-G to get to the next one. It
finds things which are: (any number of spaces or tabs), two slashes, all
characters up to the end of line.
- Alex
No, I don't think that would be workable. There are too many times when
you need to iterate over all messages without taking the parent-child
relationship into account. Having to recurse into subdirs on every one
of those occasions would give me butt cancer.
And sometimes there are "holes" in the hierarchy. Say you've got a
message but don't have its direct parent, so you hook it up underneath
its grandparent instead (this happens a LOT). But then the next day the
parent message shows up, because it just came in off the NNTP feed.
According to your scheme you'd have to re-write the file system.
For that matter, which message should go under which parent is often a
matter of some debate. Like say you've got two "sub-threads" that
really should be stuck together in the same thread, but all the
ancestors that would make that happen are gone (perhaps they've already
been read and are not displayed), so you've got a couple of "orphans."
What do you do then? MSOE and Netscape treat that situation
differently, I know that for a fact, I found that out when doing
research for PNews. By having the parent-child relationships encoded in
the file system you are effectively "hard-coding" a particular
algorithm, making it hard to change.
Instead of having to deal with the parent-child relationships only when
displaying the messages, which is a surprisingly small amount of the
total code, you'd have to deal with it ALL THE TIME. You'd get drowned
in special-case code.
Another thing: you'll probably have to write some sort of message cache.
I think everybody can agree that the absolute slowest thing about PNews
is that it takes an eternity to read all the messages in a group.
That's highest on my list of things to fix when I get to the actual
newsreader-type stuff.
>> First big stumbling block: BOutlineListView is a steaming pile of
>> poop.
>
> Maybe just ignore the Be classes and write a new one, or borrow one
> from somewhere on BeBits. Or borrow yours.
If you want it, I should probably send it to you now, before I hack it
up with stuff to make it fit into my new scheme. Right now it's pretty
straightforward BeOS code without any special dependencies.
>> Module-level comments in the header file = BETTER
>
> Nope. I've given up on header files as being useless. It's all too
> easy for comments there to get out of sync with comments in the source
> code, or just never get updated.
BLASPHEMY. That's like saying "I used to be a programmer, but my code
got BUGS in it all the time, so I quit."
Yes, they get out of sync sometimes, but my header comments are
nontheless invaluable. Remember our recent atoll() discussion? When
Michael asked about it, I couldn't remember exactly what I had to do to
get it to work on all three of my supported platforms. Fortunately I
had written myself a very nice comment in the header file that explained
it all.
Here's another one: I am up to the point of virtualizing my
thread-related classes. I had completely forgotten that MacOSX doesn't
include a recursive mutex in its pthreads implementation so I wrote one
myself, based on a non-recursive mutex. I was looking at that, and yes
it's got a mutex, and yes it's using the mutex, but it didn't seem to be
in the way I'd think it would. So I looked in the header file and found
this gem:
> CritSect has a mutex but it is not "the" mutex, if you get my drift.
> It's only there to protect the CritSect's internal data. CritSect
> knows if it's owned or not by looking at its fCount and fThread
> member variables.
Holy crap! It all made sense after that!
While refurb'ing DiskFile I couldn't remember why I'd moved the
functions to get and set the file's modified time to FileMngr instead of
leaving them in DiskFile, where they would seem to make more sense.
Header file to the rescue:
> It's impossible to implement DiskFile::TimeSet() on MacOSX because
> the act of closing the file also updates the modified time to the
> present. Therefore I moved the time get/set functions to the
> FileMngr module where they can operate on closed files.
DHUDE! Saves me moving those functions and having to find out the hard
way a second time.
>> Function-level comments that make cool pop culture references to
>> trendy people like Ellen Feiss while simultaneously disparaging
>> Windows = BEST
>
> If you say so.
Why do you hate cute adorable teenagers so much?
http://www.apple.com/switch/ads/ellenfeiss.html
Yes, viewing that will require a non-BeOS platform. But after you've
looped that baby a few times your comments will be BRIMMING with Ellen
Feiss references, you big meanie.
> BeIDE find's regex not good enough?
Yeah, your way just might work. I'll try that.
Words of wisdom. Then I'd just have the file system show the available
messages (possibly with the subject as part of the file name to make it
more Human readable) and use attributes to do the threading, much like
MDR does it (but more reliably since message IDs are available).
> I think everybody can agree that the absolute slowest thing about
> PNews is that it takes an eternity to read all the messages in a
> group. That's highest on my list of things to fix when I get to the
> actual newsreader-type stuff.
Not a bother here, but I'm using a RAM disk (OK, takes a large fraction
of a minute to dump the 400MB RAM disk back to a compressed file on the
harddisk when shutting down).
> If you want it, I should probably send it to you now, before I hack it
> up with stuff to make it fit into my new scheme.
No version control?
>> Nope. I've given up on header files as being useless. It's all too
>> easy for comments there to get out of sync with comments in the
>> source code, or just never get updated.
>
> BLASPHEMY. That's like saying "I used to be a programmer, but my code
> got BUGS in it all the time, so I quit."
Ideally comments should be doxygen style, and the IDE should display
them dynamically.
>> CritSect has a mutex but it is not "the" mutex, if you get my drift.
>> It's only there to protect the CritSect's internal data. CritSect
>> knows if it's owned or not by looking at its fCount and fThread
>> member variables.
>
> Holy crap! It all made sense after that!
That's the benefit of good comments in general. Don't need to use
headers for that, if you stuff everything into one big .c file.
Admittedly you'd turn purple and explode if you were forced to work that
way.
>> BeIDE find's regex not good enough?
>
> Yeah, your way just might work. I'll try that.
Any luck?
- Alex
I admit it: I HATE version control. Always have. "State of the art" in
that field seems so much like my early Linux experiences.
I do have old versions of my source, of course. I ZIP up an archive
about once a month or so. But that's it.
If we ever collaborate on anything, you get to be the CVS master, and I
will get very frustrated and ask very stupid questions.
> That's the benefit of good comments in general. Don't need to use
> headers for that, if you stuff everything into one big .c file.
> Admittedly you'd turn purple and explode if you were forced to work
> that way.
Hey! I think you might have read a few of my programming posts!
Between this and Michael outing me as a vampire, sheez! Just go ahead
and collaborate on my biography now, you two!
>>> BeIDE find's regex not good enough?
>>
>> Yeah, your way just might work. I'll try that.
>
> Any luck?
Your little regex trick worked great! I just got through using it to
remove all the extraneous comments from my huge-gantic TCP/IP networking
class and it took me a fraction of the time the last big module did.
See, regex's, there's another area I'm never any good at. Because a
regular expression is like a tightly-wound like program and I HATE
those. My brain looks at that thicket of punctuation and goes SYNTAX
ERROR. I want to put some air in there, break it up into sub-tasks.
There's another class of comment I make that it catches that I didn't
want it to catch, though: what looks like an end-of-line comment but is
in fact an only-thing-on-the-line comment. I want to always keep those.
I couldn't figure out how to modify the regex to overlook them but it's
no big deal, there are very few of them.
Same here. That's why I haven't learnt Perl yet, just looking at Perl
code is scary. But since I've used regex a bit in the past (grep
searches for files and BeIDE) and once a year find something new, I've
gotten familiar enough with it to use it.
- Alex