I couldn't resist upgrading to Mountain Lion right away. It's gone quite smoothly.
I have multiple machines to update, so rather than download 4 gb multiple times, I used the free Lion Disk Maker to make a "disk" that I could use on each machine. WARNING: If you want to make a disk you have to do it after you download from the App Store, but before you install (because the install removes the files). You need an 8 gb device. I didn't have an 8gb USB thumb drive handy so I used an SD card from my camera. You can do the same process manually (as I did with last time with Lion), but the disk maker utility makes it easy.
It took something like an hour to run the update from the SD card on each of my iMac and MacBook Air. I also updated to Xcode 4.4 (free from the App Store) and installed JDK 7u5 (OS X is now one of Oracle's supported platforms for Java). The extra installs were probably the wrong thing to do in terms of isolating the source of problems, but it was nice to get a bunch of updates done at once.
Here are the issues I've run into so far:
The first issue was Gatekeeper stopping me from installing programs that didn't come from the App Store. I went to turn this off but I found that you can control click on programs and override Gatekeeper, so I left it turned on.
TIP: Update all your software to the latest versions before upgrading to Mountain Lion. My iMac was up to date, but my MacBook Air wasn't. After the upgrade Parallels and Dropbox had been moved to an Unsupported Applications folder. I just downloaded and installed the latest versions and I was fine, but it would have been easier to update first.
I had to reinstall Mercurial tools (as I did when I upgraded to Lion).
When I tried to run the Java Preferences (Applications/Utilities) it said I required Java 6 and offered to install. I already had Java 6 but I told it to go ahead. It now shows Java 6 32 bit, Java 6 64bit, and Java 7. I made Java 7 my default (by dragging it to the top of the list)
Eclipse seems to work fine, but JUnit Max quit working. It seemed to be running the tests, but the success/fail indicator stayed blank. This could have been an OS X issue or it could have been from switching to Java 7. Rather than try to debug it I just switched to Infinitest. It has quite similar functionality and it's open source.
The D compiler couldn't find GCC, which I solved by re-installing the Xcode Command Line Tools (Preferences > Download)
Parallels Coherence mode has some issues with window layering that are annoying but not fatal, hopefully they'll fix it soon.
So far I haven't really noticed much difference running Mountain Lion. Despite the "200+ new features" there's not a lot that's significant to me. That's fine, I still prefer to stay on the latest version, for security improvements if nothing else.
See also: Upgrading to Lion
Saturday, July 28, 2012
Thursday, July 26, 2012
More on Parameters
We have a lot of Suneido code where the class constructor simply sets members (i.e. instance variables or fields) from its parameters:
You can also combine this with implicit dynamic parameters:
The way this is implemented, it will also work on regular methods, not just the constructor. I can't see a lot of use for that other than setters, but it was easier than restricting it.
I implemented this (along with dynamic implicit parameters) first in jSuneido, which was fairly straightforward, and then in cSuneido which was a little trickier but not too bad. (I have to say I prefer working on the Java version of Suneido these days. The code is cleaner, and the tools are better.) The changes are in version control on SourceForge.
New(foo, bar) { .foo = foo .bar = barwhich is similar to what you'd do in Java:
class C { int foo; String bar; C(int foo, String bar) { this.foo = foo; this.bar = bar;Scala has a nice shortcut for this:
class(foo: Int, bar: String) { ... }For Suneido, I decided to allow:
New(.foo, .bar)This would be equivalent to the first example. (with foo and bar still available as regular parameters as well)
You can also combine this with implicit dynamic parameters:
New(._foo)So you'd end up with a foo member in the instance, that could either be passed explicitly, or could come from a dynamic variable set in one of the callers.
The way this is implemented, it will also work on regular methods, not just the constructor. I can't see a lot of use for that other than setters, but it was easier than restricting it.
I implemented this (along with dynamic implicit parameters) first in jSuneido, which was fairly straightforward, and then in cSuneido which was a little trickier but not too bad. (I have to say I prefer working on the Java version of Suneido these days. The code is cleaner, and the tools are better.) The changes are in version control on SourceForge.
Friday, July 13, 2012
Implicit Dynamic Parameters
Don't worry if you don't understand the title - it's a term I just made up. Hopefully by the end of this post you'll know what I mean by it.
They say a big part of creativity is combining existing ideas in new ways. This idea is a combination of ideas from Suneido (via Lisp), Scala, and dependency injection.
Suneido has a little used feature where a variable that starts with an underscore is "dynamic", meaning it is available to functions that it calls, directly or indirectly. Nowadays, most languages are "statically" (i.e. lexically) scoped because that makes the code easier to understand. But Lisp (and probably other languages) had "dynamically" scoped variables where you could access variables from up the call stack.
We've never made much use of dynamic variables in Suneido and I regarded them as deprecated. I didn't even implement them in jSuneido. (Although that was partly because I thought it would be hard.) But lately I've been thinking of some uses for them, so I went back and implemented them in jSuneido. (It didn't turn out to be too hard.)
Meanwhile, Scala has something called "implicit parameters" where a parameter marked implicit can be automatically supplied by a suitable value in the current (lexical) scope. I didn't immediately see the benefits of that feature, but it does let you do some nice things.
I realized I could combine these ideas in Suneido and allow implicit parameters that can be supplied by dynamic variables. (But could still be passed "manually" as well.) A neat idea and I can see some uses, but no big deal.
Then, one of the books I'm reading was talking about dependency injection. Dependency injection relies on having some kind of "context" that does the injection. But where do you get the context from? Making it global is ugly, passing it around is ugly.
I realized that I could use my newly imagined dynamic implicit parameters to do dependency injection. Nice!
You could either use dynamic implicit parameters to inject actual dependencies, or in more complex scenarios, use it to pass some kind of context (or factory, or service locator).
For testing (or just more control) you can still pass the parameters manually.
It seems like a pretty slick idea, but of course, that's partly because it is still just an idea. The real test is when the rubber meets the road.
They say a big part of creativity is combining existing ideas in new ways. This idea is a combination of ideas from Suneido (via Lisp), Scala, and dependency injection.
Suneido has a little used feature where a variable that starts with an underscore is "dynamic", meaning it is available to functions that it calls, directly or indirectly. Nowadays, most languages are "statically" (i.e. lexically) scoped because that makes the code easier to understand. But Lisp (and probably other languages) had "dynamically" scoped variables where you could access variables from up the call stack.
We've never made much use of dynamic variables in Suneido and I regarded them as deprecated. I didn't even implement them in jSuneido. (Although that was partly because I thought it would be hard.) But lately I've been thinking of some uses for them, so I went back and implemented them in jSuneido. (It didn't turn out to be too hard.)
Meanwhile, Scala has something called "implicit parameters" where a parameter marked implicit can be automatically supplied by a suitable value in the current (lexical) scope. I didn't immediately see the benefits of that feature, but it does let you do some nice things.
I realized I could combine these ideas in Suneido and allow implicit parameters that can be supplied by dynamic variables. (But could still be passed "manually" as well.) A neat idea and I can see some uses, but no big deal.
Then, one of the books I'm reading was talking about dependency injection. Dependency injection relies on having some kind of "context" that does the injection. But where do you get the context from? Making it global is ugly, passing it around is ugly.
I realized that I could use my newly imagined dynamic implicit parameters to do dependency injection. Nice!
You could either use dynamic implicit parameters to inject actual dependencies, or in more complex scenarios, use it to pass some kind of context (or factory, or service locator).
For testing (or just more control) you can still pass the parameters manually.
It seems like a pretty slick idea, but of course, that's partly because it is still just an idea. The real test is when the rubber meets the road.
Thursday, July 12, 2012
System Programming Languages
Or, more specifically for me, languages I'd consider using to implement Suneido. Here are some opinionated thoughts on C++, Java, Scala, Xtend, D, and Go.
First, I want garbage collection. Other than for things like constrained devices, as far as I'm concerned garbage collection has won.
For me, that's a major drawback to C++. So I wrote my own garbage collector for C++ which we used for a number of years. Eventually I replaced it with the Boehm garbage collector which has worked quite well, given the limitations of conservative garbage collection.
The last few years I've been using Java which gave me great garbage collection and one of the best virtual machines out there.
The big advantage to Java is the rich ecosystem. You have multiple choices for great IDE's (e.g. Eclipse, Netbeans, IntelliJ) with good refactoring support, lots of tools like JConsole and Visual VM, good libraries, both standard and third party (e.g. Guava and Asm), and tons of books and other sources of information.
On the other hand, the Java language itself is nothing to get excited about. Lately I've been looking at Xtend and Scala. Xtend is fairly modest, it's basically a better Java. See my First Impressions of Xtend
Scala is much more ambitious. It has some great features. The claim is that the language is simpler than Java. But I'm more than a little scared of the type system. Although it's that type system that allows some of the great features. Scala strikes me a bit like C++, you can do some amazing things, but it can also get pretty twisted.
I'd be more tempted by Scala, but as system programming languages, JVM language all have a major drawback - you can't write efficient low level code. Don't get me wrong, I have no desire to write "unsafe" code. I don't want to go back to my C and C++ days. Java has primitive (non-heap) types, but they don't work with generic code (without boxing onto the heap). I'd like to have "value" types (e.g. a pair of ints) that I could pass and return by value (not on the heap) and embed (not reference) in other data structures. Scala tries to unify primitives with the other types, but ultimately it comes down to the JVM, and there's still a lot of boxing going on.
Also, Java is primarily in the locks and shared state style of concurrency, a style whose drawbacks are well known. Scala is better on this front with its actor system, which admittedly is also possible from Java.
What else is out there? C# is a possibility, but I have to say I'm leary about Microsoft products. And portability means Mono, which is another question mark in my mind.
Recently I've been rereading the D book by Andrei Alexandrescu (also author of Modern C++). You can get a taste of his writing style in The Case for D. In some respects the D language could be called a better C++. But it has gone beyond that and has some very attractive features. It has value types as well as reference types. You can write efficient code like C++, but still make it safe.
D has garbage collection, although I suspect (with no evidence) that it's not as good as the JVM. Of course, part of the reason so much effort has gone into JVM garbage collection is that everything has to go on the heap. That doesn't apply quite so much in D (depending on the style of your code).
One of the features I really like about D is its support for immutability and pure functions. My feeling is that these are really important, especially for concurrent code. You can, of course, write immutable data structures and pure functions in any language, but D actually lets you enforce them. Unlike C++ const or Java final, D's immutable and pure are "deep". Making an array final in Java doesn't stop you from modifying the contents of the array. Making an array immutable in D does.
One minor disappointment is that D still requires semicolons. I think languages like Scala and Go have shown that it's quite feasible to skip the semicolons. But I could live with this.
I'm not against virtual machines like the JVM or CLR. But they have their drawbacks, especially for deployment. Ensuring that customers have the right version of .Net is bad enough and that's a Microsoft product on a Microsoft platform. We can require our customers install Java, but when they don't update it and there's a security hole, guess who they will blame? One of Suneido's main features is that it is self contained and easy to deploy. Requiring another runtime underneath it is not ideal. So D and Go generating native apps is attractive in this respect.
Another advantage to D is that (I think) it would allow accessing the Win32 API so Suneido's current user interface would still work. (albeit still only on Windows.)
Yet another possibility is Google's Go language. Personally I find it a little quirky. It's got some good features, but it's also missing things that I like (e.g. type safe containers). I'm currently reading Programming in Go but I'm finding it somewhat dry. I find it a lot easier to learn about a language from a well written book. I didn't really get interested in D until the book came out. And books got me interested in C and C++ and Scala.
One of the things discouraging me from Scala and D and Go is the lack of IDE support. That's gradually improving, but things like refactoring are still pretty limited. I programmed for years with just an editor, but once you get accustomed to a good IDE with refactoring support, it's hard to go back. To me, one of the big advantages of a statically typed language is that it allows great tooling. Unfortunately, Java seems to have a big lead in this area.
Currently, if I was to consider another language for implementing something like Suneido, I think I'd lean towards D.
First, I want garbage collection. Other than for things like constrained devices, as far as I'm concerned garbage collection has won.
For me, that's a major drawback to C++. So I wrote my own garbage collector for C++ which we used for a number of years. Eventually I replaced it with the Boehm garbage collector which has worked quite well, given the limitations of conservative garbage collection.
The last few years I've been using Java which gave me great garbage collection and one of the best virtual machines out there.
The big advantage to Java is the rich ecosystem. You have multiple choices for great IDE's (e.g. Eclipse, Netbeans, IntelliJ) with good refactoring support, lots of tools like JConsole and Visual VM, good libraries, both standard and third party (e.g. Guava and Asm), and tons of books and other sources of information.
On the other hand, the Java language itself is nothing to get excited about. Lately I've been looking at Xtend and Scala. Xtend is fairly modest, it's basically a better Java. See my First Impressions of Xtend
Scala is much more ambitious. It has some great features. The claim is that the language is simpler than Java. But I'm more than a little scared of the type system. Although it's that type system that allows some of the great features. Scala strikes me a bit like C++, you can do some amazing things, but it can also get pretty twisted.
I'd be more tempted by Scala, but as system programming languages, JVM language all have a major drawback - you can't write efficient low level code. Don't get me wrong, I have no desire to write "unsafe" code. I don't want to go back to my C and C++ days. Java has primitive (non-heap) types, but they don't work with generic code (without boxing onto the heap). I'd like to have "value" types (e.g. a pair of ints) that I could pass and return by value (not on the heap) and embed (not reference) in other data structures. Scala tries to unify primitives with the other types, but ultimately it comes down to the JVM, and there's still a lot of boxing going on.
Also, Java is primarily in the locks and shared state style of concurrency, a style whose drawbacks are well known. Scala is better on this front with its actor system, which admittedly is also possible from Java.
What else is out there? C# is a possibility, but I have to say I'm leary about Microsoft products. And portability means Mono, which is another question mark in my mind.
Recently I've been rereading the D book by Andrei Alexandrescu (also author of Modern C++). You can get a taste of his writing style in The Case for D. In some respects the D language could be called a better C++. But it has gone beyond that and has some very attractive features. It has value types as well as reference types. You can write efficient code like C++, but still make it safe.
D has garbage collection, although I suspect (with no evidence) that it's not as good as the JVM. Of course, part of the reason so much effort has gone into JVM garbage collection is that everything has to go on the heap. That doesn't apply quite so much in D (depending on the style of your code).
One of the features I really like about D is its support for immutability and pure functions. My feeling is that these are really important, especially for concurrent code. You can, of course, write immutable data structures and pure functions in any language, but D actually lets you enforce them. Unlike C++ const or Java final, D's immutable and pure are "deep". Making an array final in Java doesn't stop you from modifying the contents of the array. Making an array immutable in D does.
One minor disappointment is that D still requires semicolons. I think languages like Scala and Go have shown that it's quite feasible to skip the semicolons. But I could live with this.
I'm not against virtual machines like the JVM or CLR. But they have their drawbacks, especially for deployment. Ensuring that customers have the right version of .Net is bad enough and that's a Microsoft product on a Microsoft platform. We can require our customers install Java, but when they don't update it and there's a security hole, guess who they will blame? One of Suneido's main features is that it is self contained and easy to deploy. Requiring another runtime underneath it is not ideal. So D and Go generating native apps is attractive in this respect.
Another advantage to D is that (I think) it would allow accessing the Win32 API so Suneido's current user interface would still work. (albeit still only on Windows.)
Yet another possibility is Google's Go language. Personally I find it a little quirky. It's got some good features, but it's also missing things that I like (e.g. type safe containers). I'm currently reading Programming in Go but I'm finding it somewhat dry. I find it a lot easier to learn about a language from a well written book. I didn't really get interested in D until the book came out. And books got me interested in C and C++ and Scala.
One of the things discouraging me from Scala and D and Go is the lack of IDE support. That's gradually improving, but things like refactoring are still pretty limited. I programmed for years with just an editor, but once you get accustomed to a good IDE with refactoring support, it's hard to go back. To me, one of the big advantages of a statically typed language is that it allows great tooling. Unfortunately, Java seems to have a big lead in this area.
Currently, if I was to consider another language for implementing something like Suneido, I think I'd lean towards D.
Monday, July 09, 2012
Struggling with Eclipse CDT
I just spent a frustrating day trying to get Eclipse CDT set up to work on cSuneido (C++).
I've tried this several times in the past but always had problems and given up.
Every time a new version of Eclipse comes out I read about the improvements in the CDT (C/C++ Development Tooling) project and I feel guilty that I'm not using it and embarrassed that I'm too stupid to set it up.
Surely if I just devoted some time to it I could get it working. Maybe, but a day wasn't enough time, and I'm not sure how many days I can stand banging my head against the wall on it.
I realize that a portable C++ IDE is a tough problem. C++ is a gnarly language, and there are multiple versions of multiple compilers. A good IDE has to actually understand the language, which means it has to deal with all the intricacies of C++. I'm sympathetic.
But when I take a clean install of MinGW GCC (one of the supported compilers), and a clean install of Eclipse Juno CDT, and let it create a sample "hello world" project, I'd expect it to work. Not for me. It took me a couple of hours to get rid of the errors in this 10 line project. And even after all that, I was no further ahead than when I started. I just thrashed around with the myriad settings until some combination worked. No doubt most of my thrashing made things worse and just muddied the waters, but what else can you do?
The problems were mostly related to getting the right include paths. That seems like a straightforward problem, that should have a straightforward solution. But there are about four different places where you can set up include directories, and at least two different "auto discovery" systems that try to do it for you. And it's not enough to give c:/mingw/include, that would be way too simple. Instead you have to give every sub-directory that mingw happens to use, most of which are under the lib directory for some reason.
It was doubly frustrating because the project would "build" and produce a runnable executable, all while showing major errors.
Searching the web wasn't much help. Lots of other people have similar problems, although mostly with older versions of Eclipse and CDT so the settings they talk about no longer even exist.
There is an "indexer" which also gives compile type errors, plus multiple "builders", including "managed" ones, and ones that use your makefiles, and ones that generate makefiles. I couldn't tell whether errors were coming from the indexer, or something calling the actual GCC compiler, or from linking, or who knows where.
Eventually I got hello world to build and not show any errors so I moved on to Suneido, albeit with a certain amount of trepidation. I managed to get the include directories sorted out without too much trouble since I had a vague idea of which areas to semi-randomly play with the settings.
Nevertheless, several times I had to exit completely out of Eclipse because it got into seemingly infinite loops of building the project over and over. I don't know what triggered this or how to avoid it.
By the end of the day I managed to get rid of all the actual errors, although there are still a ton of warnings. Part of the problem is that once you have an error, it may not go away even if you fix the problem. I spent all my time running Clean and Build and re-indexing in attempts to figure out if I had fixed the problem or not.
A bunch of the warnings were from functions that weren't returning values. This weren't bugs, they were calling functions that never returned (e.g. threw exceptions or exited). The functions were marked with __attribute((noreturn)) and this works fine in GCC. But not in CDT. I found an Eclipse bug for this and left a comment, but I hadn't been able to isolate a simple test case so, predictably, the response was less than satisfying.
(Note: The Suneido C++ code builds fine with both GCC and Visual C++ using make)
I really wanted this to work. I am quite happy with Eclipse with my jSuneido Java code. I would really like to have better navigation and refactoring tools for C++. But even if I could get it working without tearing all my hair out, I have zero confidence that it's going to be a stable platform for development. All I can envision are things breaking randomly and unpredictably with cryptic errors.
I don't blame the CDT developers. They've got a tough job and I'm sure it would have taken them minutes to sort out what I flailed on for a day. But in the end, that doesn't help me get my work done.
Maybe I'll look at the latest NetBeans - I haven't tried it lately. Of course, I'm even less familiar with NetBeans than I am with Eclipse, which doesn't bode well!
I've tried this several times in the past but always had problems and given up.
Every time a new version of Eclipse comes out I read about the improvements in the CDT (C/C++ Development Tooling) project and I feel guilty that I'm not using it and embarrassed that I'm too stupid to set it up.
Surely if I just devoted some time to it I could get it working. Maybe, but a day wasn't enough time, and I'm not sure how many days I can stand banging my head against the wall on it.
I realize that a portable C++ IDE is a tough problem. C++ is a gnarly language, and there are multiple versions of multiple compilers. A good IDE has to actually understand the language, which means it has to deal with all the intricacies of C++. I'm sympathetic.
But when I take a clean install of MinGW GCC (one of the supported compilers), and a clean install of Eclipse Juno CDT, and let it create a sample "hello world" project, I'd expect it to work. Not for me. It took me a couple of hours to get rid of the errors in this 10 line project. And even after all that, I was no further ahead than when I started. I just thrashed around with the myriad settings until some combination worked. No doubt most of my thrashing made things worse and just muddied the waters, but what else can you do?
The problems were mostly related to getting the right include paths. That seems like a straightforward problem, that should have a straightforward solution. But there are about four different places where you can set up include directories, and at least two different "auto discovery" systems that try to do it for you. And it's not enough to give c:/mingw/include, that would be way too simple. Instead you have to give every sub-directory that mingw happens to use, most of which are under the lib directory for some reason.
It was doubly frustrating because the project would "build" and produce a runnable executable, all while showing major errors.
Searching the web wasn't much help. Lots of other people have similar problems, although mostly with older versions of Eclipse and CDT so the settings they talk about no longer even exist.
There is an "indexer" which also gives compile type errors, plus multiple "builders", including "managed" ones, and ones that use your makefiles, and ones that generate makefiles. I couldn't tell whether errors were coming from the indexer, or something calling the actual GCC compiler, or from linking, or who knows where.
Eventually I got hello world to build and not show any errors so I moved on to Suneido, albeit with a certain amount of trepidation. I managed to get the include directories sorted out without too much trouble since I had a vague idea of which areas to semi-randomly play with the settings.
Nevertheless, several times I had to exit completely out of Eclipse because it got into seemingly infinite loops of building the project over and over. I don't know what triggered this or how to avoid it.
By the end of the day I managed to get rid of all the actual errors, although there are still a ton of warnings. Part of the problem is that once you have an error, it may not go away even if you fix the problem. I spent all my time running Clean and Build and re-indexing in attempts to figure out if I had fixed the problem or not.
A bunch of the warnings were from functions that weren't returning values. This weren't bugs, they were calling functions that never returned (e.g. threw exceptions or exited). The functions were marked with __attribute((noreturn)) and this works fine in GCC. But not in CDT. I found an Eclipse bug for this and left a comment, but I hadn't been able to isolate a simple test case so, predictably, the response was less than satisfying.
(Note: The Suneido C++ code builds fine with both GCC and Visual C++ using make)
I really wanted this to work. I am quite happy with Eclipse with my jSuneido Java code. I would really like to have better navigation and refactoring tools for C++. But even if I could get it working without tearing all my hair out, I have zero confidence that it's going to be a stable platform for development. All I can envision are things breaking randomly and unpredictably with cryptic errors.
I don't blame the CDT developers. They've got a tough job and I'm sure it would have taken them minutes to sort out what I flailed on for a day. But in the end, that doesn't help me get my work done.
Maybe I'll look at the latest NetBeans - I haven't tried it lately. Of course, I'm even less familiar with NetBeans than I am with Eclipse, which doesn't bode well!
Monday, July 02, 2012
Moving from Eclipse Indigo to Juno
Eclipse 4.2 Juno was released on June 27. Usually I wait a while to make sure that plugins have been updated to work with the new version, but I thought I'd give it a try and I found that all my plugins still worked.
So far I haven't run into any problems with Juno. I've seen some complaints about the UI changes, but I don't mind it. I got a few warnings from the new null analysis, although none of them turned out to be actual problems.
I did run into an old problem when I updated my C++ (CDT) copy of Eclipse - it crashed on start up. I knew I'd run into this before but I couldn't remember the solution. It turned out to be a bug in some versions of Java. I found I wasn't running the latest and after I updated the problem went away. See Bug 333227
It is possible to update an install of Eclipse 3.7 to 4.2 in place, but I prefer to do a clean install from a fresh download. It may be overly paranoid but I figure it can't hurt to start fresh. You can move your plugins over from a previous install using File > Import > Install > From Existing Installation. This saves re-installing them one at a time.You can also move your Preferences over by exporting them from your old copy and importing them into the new one. I haven't found any way to move my perspective layouts, but my normal layout is simple to recreate.
From my experience, if you're running Eclipse, I'd say give Juno a try.
So far I haven't run into any problems with Juno. I've seen some complaints about the UI changes, but I don't mind it. I got a few warnings from the new null analysis, although none of them turned out to be actual problems.
I did run into an old problem when I updated my C++ (CDT) copy of Eclipse - it crashed on start up. I knew I'd run into this before but I couldn't remember the solution. It turned out to be a bug in some versions of Java. I found I wasn't running the latest and after I updated the problem went away. See Bug 333227
It is possible to update an install of Eclipse 3.7 to 4.2 in place, but I prefer to do a clean install from a fresh download. It may be overly paranoid but I figure it can't hurt to start fresh. You can move your plugins over from a previous install using File > Import > Install > From Existing Installation. This saves re-installing them one at a time.You can also move your Preferences over by exporting them from your old copy and importing them into the new one. I haven't found any way to move my perspective layouts, but my normal layout is simple to recreate.
From my experience, if you're running Eclipse, I'd say give Juno a try.
Subscribe to:
Posts (Atom)