How I learned to stop hating the command line (so much)

english mobile

I'm old. So I still remember when every computer screen looked like what we now call "the command line." Screens were black and text was green or amber. Anything you needed to do on the computer took forever and depended on your ability to remember lots of commands and type them correctly. This made computing seem difficult and unapproachable. So when the first MacIntosh computers showed up in the Art Department where I was studying, I was as happy as anyone.

Finally, it was (more or less) obvious how the computer was organized, and figuring out how to do things and what you could do was easy and intuitive. When I first used a Windows 3.1 computer, I was even more delighted. And so I have been a relatively happy camper for many years. Of course there have been difficulties and frustrations, but by and large if there was any task worth doing someone had built an interface that made it easy to do things without having to remember tedious commands and type them accurately. This allowed me to reserve my head space for the problems that actually interested me and/or I had been hired to solve.

I recently started learning AngularJS, and I was dismayed to find that before you can even start with Angular, you have to do a fair amount of work in the command line. Not only that, but there's little explanation of why you need to do these steps and no explanation of whether there are alternate routes to accomplish the same thing. I get that when you're trying to write a tutorial if you try to cover every last bit of background information someone might want to know that you'd never get finished.

However, the absence of such supporting information right now means that if you want to learn AngularJS (and I suspect many other current JavaScript frameworks) you're stuck using the command line whether you like it or not. You may not be surprised to learn that I don't especially like it. I've learned a few things over the past couple of months that make me dislike it a lot less. So if you share my dislike of the command line, keep reading and maybe we can make life a little easier.

Why we need the command line

As my elementary school teachers could tell you, I've never been especially fond of just doing things without knowing why. So let's start with why it is that it seems everything needs to go through the command line. The answer is simple (but seldom articulated): nodejs. Node was designed as a server-side technology, so the only facility it has for drawing to the screen is a browser that's pointed to a site that it's serving. However, most of the tools you use during JS development aren't conceived that way and I have no idea if they could be.

You get a few things from node that nearly make its lack of a decent UI worth it.

  1. Node lets you run a webserver (or several) out of any directory on your computer. Unlike more traditional web servers such as IIS or Apache, Node lets you just fire up a server anywhere. Security considerations aside, it's pretty cool that you're now free to put your code in whatever directory makes sense for development rather than the directory that the web server can see (or that you've set up as a virtual directory). You can even have one server running the site and another server running the unit tests.
  2. Node Package Manager (npm). Npm is like a magic registry in the sky that will allow you to more or less instantly download and install most tools and libraries you'll need for doing Javascript development. It will also make sure that if those tools have dependencies that the libraries they depend on are also installed, even if the different tools depend on different versions of the same library.
  3. Many of the tools are also in node or at least depend on it/run on top of it. For example, Karma test runner launches a node server on its own port to run the tests.

So we kind of have to use it, or at least get enough benefit from it that we can grit our teeth and use the command line. I had several pain points that were driving me flat up the wall, so I'd like to share some solutions that made things easier for me.

Navigating to directories

Directories to me are only significant as a way to keep things organized and insofar as they affect whether my code runs properly or not. It's not even on my radar to be interested in constantly typing (correctly, no less) CD and the full path to the directory where my code lives. So yes, I know from a stint doing embedded development on a Linux device a few years ago that to some extent you can get the CLI to type paths for you by typing the first letter or two of each directory and pressing the tab key. But that's only slightly less tedious. After several days of this, I got really annoyed and went searching.

What I found is that on Windows you can hold down the shift key while right-clicking on a folder. This adds "Open a command prompt here" to the context menu. Note that this is in a different spot on the context menu depending if you right-click on the left pane (shown) or the right pane.

Mac/Linux people, I am sure Google can tell you similar shortcuts for your environment. The point is you don't have to type the path over and over.

Typing the same crap over and over

If I enjoyed typing the same crap over and over, I probably wouldn't have decided to be a programmer. But as I got into the red-green rhythm of testing, I found myself typing karma start (red), karma start (green), cls (if the test passed, clear the screen and on to the next test).

Again, my vague memories came to the rescue and I remembered that you can use your up and down arrow keys to rerun the same commands again. So, once I'd typed karma start once, I could run it again by pressing the up arrow key once and pressing Enter. Then, after typing cls, two up arrows goes back past cls to karma start. From there, one up arrow goes to karma start again, or a down arrow goes to cls.

Yes, Mac users, I know that you use a different command to clear your screen, but I don't know it off the top of my head. Usually I run bootcamp on any Mac I use. But the idea is the same.

Not being able to read the text

Like I said, I'm old. I also enjoy sparring in karate, so my glasses may not sit exactly where they're supposed to on my head. So the red karma uses for a failed test is completely illegible to me on the default black background. Karma has about four colors I have seen:

  • Medium gray for ordinary text
  • Green for passing test
  • Red for failing test
  • Teal for console.log

I vaguely think I remember seeing yellow, but I don't remember what they were doing with it.

All this variability means that it can be tough to find a background color that works. Let's not talk text colors, because node and karma change them anyway. In karma, you have the choice of "use colors" or "don't use colors," but there is no "use better colors." Anyway, my experience is that a white background gives the best legibility across the most frequently-used colors. It's a shame, because it seems that "real developers" use darker color schemes, but there you have it.

One problem with setting the background color is that any time you run npm install, node will helpfully change your background color to black. I haven't found any way to get it to stop doing this, but if you set your defaults, you can just close the window and reopen it using the right-click menu described above. To set the defaults, just click the icon in the upper left of the command prompt and select "Defaults."

Future plans

For those wondering why I launch karma over and over rather than just leaving it running, I'm planning an entire post on karma setup in the future.

Deja vu all over again

english mobile

When I started this blog in 2007, I had been developing in a technology called Authorware that Adobe was in the process of killing off. So I decided to concentrate on teaching myself Flex, sharing what I was learning with others who were also making that transition.

I still work in Actionscript a lot, primarily in Flash, but unfortunately I've had to come to the decision that it's not the best use of my time to blog about some of the neat things I'm still doing.

It's not fair to say I'm learning JavaScript, since I've been doing JavaScript in some form for over ten years, but I am learning about the JavaScript ecosystem as I find it in 2014, particularly surrounding AngularJS. I'm shifting focus to once again ramp up in tools that are relevant instead of ones that are becoming less relevant. In the process, hopefully I can help others who are making a similar transition or just who want to learn about the parts of the process that I delve into. I like to think that I'm willing to write about things that others may not feel are glamorous enough to devote time to but that can be incredibly helpful if you're looking for just that information.

I have decided to keep the title of the blog the same. In part this is because I have some loyal readers who have been with me the whole way. In part this is because I think that the AngularJS world will realize in time that the particular experience that former Actionscript developers, especially Flex developers, bring to the table means that we're very well-suited to do things the "Angular way." I hope you enjoy the new direction.

ActionScript, E4X, and White Space

english mobile

I've been reading XML into ActionScript 3 for many years, and I still haven't solved all the issues with it. Given that my searches for solutions to these issues turn up so little, I decided to share the solutions I have found, especially when it comes to white space.

I think at least part of the reason that these problems are so hard to solve is that the XML documentation for many of the properties and methods we need to use is frustratingly circular. So let me start by laying out what some of these do in practice.

ignoreWhiteSpace

I think ignoreWhiteSpace is the property we first try to use to correct some of the issues with E4X. This property will, in fact, fix issues that are caused by having "extra" children that you weren't expecting to be parsing when you use normal formatting, like new lines and tabs, in your XML. However, it then causes other white spaces that might have been pretty important to disappear.

An alternative to using ignoreWhiteSpace is to use xmlVar.elements() instead of xmlVar.children(). This works relatively well unless you need to access something that's not an element, like a comment, or you need to pass the XML to Adobe code (like new DataProvider()) that for some reason is not equipped to handle the vagaries of their own E4X implementation.

prettyPrinting

We're all familiar with the problem where the default XML parsing adds even more formatting than we included in the original XML file, so that

<root>
 <p>The quick brown fox jumped over the
 <b>lazy</b> dog.</p>
</root>
becomes
<root>
 <p>The quick brown fox jumped over the 
  <b>lazy</b> 
 dog.</p>
</root>

I'm sure there are some versions of Flash where setting prettyPrinting to false fixes this problem, but in the version of the Flash player we target, setting this property has no effect. The good news is that TextField, the Flash Label component, and the Flex MX Label component support the condenseWhite property, which gets rid of this issue for text you want to display. I guess if you're using a spark label, the skin will need to use something that supports condenseWhite if you need this.

Wrap in CDATA

One of the reasons XML parsing is so thorny is that we're using the XML to store external content, often HTML-formatted. CDATA does work to preserve HTML formatting, but it has its own issues. One issue is that there's no real documentation about how to get the text out of CDATA.

Funny story--I was once on a Flex project where it turned out I needed to wrap the entire XML package I was building in CDATA. Try though I might, I couldn't find anything that told me how to get at the "stuff" inside the CDATA. With deadline fast approaching, I "hacked" it by giving the text to a Spark label (which did know how to do this), then reading the text out again and casting it to XML.

Some months later, I ultimately discovered that String(myNode) will retrieve the contents of a node, whether its contents are wrapped in CDATA or not. Unless the contents are not wrapped in CDATA but contain HTML formatting anyway. This is something that is quite likely to happen on my team, as the people who produce the XML see no reason they shoulld start wrapping everything in CDATA just because we're using ActionScript 3 now.

In addition, even when things are wrapped in CDATA when they should be, you have to dump your text in one line into CDATA because it faithfully reproduces all those \n's and \t's, and you wind up with a bunch of junk nodes if you have to cast the contents back to XML. This results in XML that isn't readable, and readability is one reason to use XML in the first place.

hasComplexContent

So, if you're getting XML and you know that sometimes certain nodes will contain HTML and sometimes that HTML will be wrapped in CDATA and sometimes it won't, what do you do? One thing you can do is create a function that checks for hasComplexContent and calls toString() if it returns false and children().toXMLString() if it returns true.

This works well, but one issue with it is you have to have access to this function wherever you're parsing XML. And since you can't really extend the XML Class, due to its dependence on static methods and properties, that means you either need to use a static method yourself (not my favorite thing) or you need to violate DRY, unless your application lends itself to only parsing XML nodes in exactly one place.

normalize()

This is probably my favorite method, because it gets rid of all the weird child nodes that contain "\n\t\t". This means that I can now parse formatted XML and not have to allow for weird extra junk in there. More importantly, I can pass that XML to "dumber" code, such as the Flash DataProvider constructor, and it works. It also does not take out the spaces around inline HTML tags, so you can normalize() the XML to make for easy parsing that you should get from ignoreWhiteSpace (but don't, due to the removed spaces), then you can call String(myXMLNode) on the node whether it has complex content or not, and it will work in a TextField with condenseWhite set to true. FTW!

Batch Import Images into Flash Symbols

english mobile

When I find a workflow I like, I sometimes assume that everyone has already discovered that workflow, and I'm late to the party. One of the nice things about participating in user forums is that sometimes that helps me realize that a favorite workflow isn't known to everyone. This is great, because then I have something to blog about!

Today, I want to talk about what is probably one of my all-time best productivity tricks in Flash. In a few minutes, I can:

  1. Import a series of pngs, jpgs, or whatever into my Flash movie
  2. Choose for each image to be wrapped in a symbol or not
  3. Have the symbols and images nicely organized into folders in the library, without any extra effort!
Here's how I do it, starting with a folder of images:

Step 1: Browse the folder in Bridge

First, I right-click on the folder of images and select "Browse in Adobe Bridge"
Once it opens, I select the images I want to use. For this post, I just selected everything in the directory, but Bridge has excellent features for finding just the images I want (that could be a blog post in itself). You can drag them around in Bridge to change the order, if you need to.

Step 2: Load the files into PhotoShop Layers

In the Bridge "Tools" menu, I select PhotoShop>Load Files into PhotoShop Layers.

This launches PhotoShop and does all the work to put the files into PhotoShop layers, in the order they were in in Bridge. Once that has finished running, save the result as a .psd.

Step 3: Create a Symbol in Flash to Import into

Whenever I have to create a new Symbol in Flash, I like to start with a rectangle that's the size I want the MovieClip to wind up, so the registration and transformation points fall in predictable places. So, I create a rectangle the size of my images and convert it to a Symbol (F8).

Step 4: Import the PSD

I usually use the keyboard shortcut to import to stage (Ctrl-R). The import dialogue gives me lots of options. For example, I can select all the images and choose to convert them to MovieClips.
I'll usually convert the images to MovieClips if I want to do timeline animation with them or if I want to apply a base Class to the MovieClip. I can also choose to import each to a different layer or to a different keyframe. Both options are useful, depending on the end result I need.

Once the psd has imported, the timeline looks like this.

Note that the frames will be the reverse order of the order they were in in Bridge. I usually select the frames and reverse the frames (there's a right-click menu for it, but I've set up a keyboard shortcut).

Step 5: Edit the Library Symbols

The MovieClips and Images are nicely organized, but usually there is more I want to do to them.
If I'm applying a Base Class, I might want to rename all the Symbols, for instance, to change ".png" to "_png." I like the Search and Replace extension for this.

Flash also allows you to edit more than one library symbol at a time, by selecting several symbols and clicking the Properties button (sorry, if there is a shortcut for this, I haven't found it).
From this dialogue, you could change all the MovieClips to Graphics, for example, or you could set a Base Class on all the MovieClips at once. Tip: if you set a Base Class, Export for ActionsScript will become checked and the drop-down will have "Yes" selected, and you don't have to touch it.

And that's it, my quick and easy workflow for importing a series of images to Flash.


FlashTips #6: Debug refresh issues in your swf

english mobile

Most of us know that Flash Builder makes it easy to debug a swf on a server by creating a custom debug configuration. Recently, I had a problem where I needed to be able to debug issues that happened when the browser window was refreshed.
Jeffry Houser, the brains behind Flextras.com, apparently had this very same problem, and resolved it by starting a new debugger session that points to about:blank and then connecting that to the swf after the window has been created.
That's a great solution, but the issue I was having was happening pretty much immediately after the window was refreshed--if I went through his steps, I'd "miss the window." So, after limping along for several hours, trying to figure out the problem without having the direct debug information, I finally figured out that the problem was amazingly simple:

  1. Create a new "refresh" debug configuration that doesn't point to a page with a swf in it (I didn't yet know that about:blank was an option).
  2. Start the original debug configuration, that points to the swf as normal.
  3. Get to the problem point in the application.
  4. Launch the "refresh" configuration.
  5. Refresh the window.
  6. Voilà, we are connected, from the very beginning of the bootstrapping process.
Enjoy!

Reusing a Flash Builder Workspace

english mobile

I use Flash Builder and Flash Pro together, and over time I have learned to just bow to how Flash Builder wants me to do things. What this means is that each "family" of Flash files has to have its own Workspace, because Flash Builder expects the Flash file to be in a subdirectory of the workspace in a directory that's the named the same thing as the Flash file. If that's not where it is, you either have to remember to tell Flash Builder not to use its default or things go very wrong, very fast.

In a team environment, the process has to be as simple as possible, without a bunch of fiddly steps that people have to remember to do at exactly the right moment, so it's just easier to go with what Flash Builder wants us to do. However, this adds other fiddly steps that people need to do each time they start a new workspace, such as importing snippets and laying out all the panels just so.

So I thought I'd hit on a brilliant plan, which is just to check the workspace settings into version control that live in the .metadata folder. This way, everyone would get a workspace that's already set up when they export the "base" Flash project and they could just start working. And this does work for the intended purpose, but I found that workspace relative paths would break (paths that refer to the ${DOCUMENTS} variable). These would unaccountably point to the original base project directory.

On Windows, for whatever reason a file contents search didn't turn up the offending string. I suspect this has to do with the weird way the .metadata folder starts folder and file names with "." So I was off to Google to try to find out how other people transfer their settings. I found one post that suggested you just copy the .metadata/plugins/org.eclipse.core.runtime/.settings directory. The result I had from that was that the site relative root now pointed to the project I'd copied the directory from. At least now I had it narrowed down to a large handful of files that I could then open and look at individually.

To save you the bother, I'll tell you that the file that contains the location of the workspace for workspace-relative links in the above directory is called org.eclipse.core.resources.prefs, and that file contains the pathVariable.DOCUMENTS string that tells Flash Builder/Eclipse where the workspace thinks it is. I haven't had a chance to play with it to see if simply not putting that file in version control makes things better or borks them, but even if everyone has to manually update that variable when setting up a project it's much better than having to set up every workspace from scratch when we start a new project.

My favorite Flash Builder Code Templates

english mobile

I hate typing the same code over and over, and DRY can only take you so far. I also hate making the same changes over and over. So I've "tweaked" some of the templates that came with Flash Builder and I've added many to automate the tasks I do frequently. I've made them available for download. You'll need to unzip the file and import the template file into your ActionScript code templates, or you can copy and paste any you find useful.

My version of the fori

I loop through lots of things other than Arrays, and when I do loop through Arrays, I don't like to read the length on every loop. So I've modified the fori template.
for (var ${index}:int = 0; ${index} < ${loopVar}; ${index}++) {
 ${line_selection}${cursor}
}

Looping through MovieClip/Sprite Children

A lot of times, I have a Class where I just know I'll have "some" instances of a specific type, but I don't want to dictate in advance how many that will be. So often I'll have code to find those children. I call this template "childLoop."
var loops:int = numChildren;

for (var i:int = 0; i < loops; i++) {
 var ${varName}:${search_type} = getChildAt(i) as ${search_type};
 if (${varName}) {
  ${cursor}
 }
}

Push into an Array/Vector

Often, inside a child loop, I'm inserting the children that match into a Vector. It's supposed to be faster to use the length property of an Array or Vector to add to it instead of using push(), so when I'm adding to the end of one of these, I use my "fastpush" template.
${arrayOrVector}[${arrayOrVector}.length] = ${newItem};

Sort the Vector

Often, the instances aren't added to the stage in the correct order to match each with the piece of data that goes with it, so I have various sorting functions on hand, such as "leftToRightSort" that can be applied as the sort function to the Vector.
protected function leftToRight(btnA:DisplayObject, btnB:DisplayObject):Number {
 return (btnA.x - btnB.x);
}

If setter value has changed

Flash Builder has a great feature to generate a getter/setter pair from a variable declaration. Even through I'm working in Flash, I often check the box that allows you to dispatch a custom binding event (which doesn't do much in Flash, unless you wire it up yourself). What I do get from that is auto-generated code that checks to see if the variable's value has changed before doing something, such as removing/adding event listeners. Sometimes I forget to check that box or I decide that I don't want the overhead of having the event dispatched and I think that deleting that extra code is more effort than what advantage I get out of using the check box. In those cases, I add essentially the same code with the "ifValueChanged" template.
if(${myVar} != value) {
 ${myVar} = value;
 ${cursor}
}
Do you have favorite code templates? Please share in the comments section.