Cocktail Arcade Cabinet Upgrade: Part 2 - Early Impressions and Software Changes

| Comments

It has been about two weeks since I hung the new television on the wall behind the arcade table. Most of what I’ve done since then is set up some scripts to automate the resolution and screen orientation settings, and also tweaking all the emulators and native games to use the correct resolutions and orientations.

I’ve run into some problems, but I’ve also found some solutions. One of the solutions is causing new problems. The upgrade has been fun, and I have some new ideas to implement later on.

WahCade menu on the big screen Mutant Mudds

Early impressions of the “hybrid” arcade cabinet

I really like it. It reminds me of playing while sitting on one of those big, red stools in a real arcade back when I was a bit too small to see the screen well from the ground.

I’ve spent quite a bit of time tweaking native game settings. I assumed that I’d get every game set up in just an hour or two. It didn’t work out that way because it is impossible not to play some of these games once you fire them up. I probably spent at least two hours replaying Cave Story Plus.

It does feel like I am cheating a bit. It feels less authentic, but I think I can live with that.

nvidia-settings, disper, and xrandr

At first I was using disper to control the resolution and which of the two displays were active. However, disper and nvidia-settings are unable to control the rotation of a single display, and I need to be able to run the “internal” monitor inverted. Preferably I should be able to rotate it on the fly, since the rotation results in a HUGE (4+ times) slowdown, and some games just won’t run fast enough that way.

I started out running Nvidia’s 295.49 drivers that ship with Ubuntu 12.04. I upgraded them to the 304.51 version because they are supposed to have proper support for xrandr 1.3.

They very nearly do. I can independently control the resolution and rotation of each display with xrandr. It won’t let me use xrandr to add modelines to either display. This is problematic because the internal monitor has a 1360x768 modeline and the external television has a 1280x720. There are a handful of resolutions they don’t share.

I can still set any resolution I can think of using disper. So now I’m using a disper to activate displays and set their resolution and I’m using xrandr to set the orientation of the internal display.

Another small difference between 295.49 and 304.51

The 295.49 driver was quirky with regard to the television. It would only drive it at 1920x1080 or 1280x720. Everything else would be scaled up. This made it easy to get aspect-correct scaling for modes like 640x480 and 800x600.

The 304.51 “fixed” this problem for me. It will happily drive the television at 640x480 or 800x600. I should be excited about this, but suddenly many of the games that I set up are now scaled incorrectly.

I’ll have to work on this one a bit more.

I’m all out of buttons

I’d like to be able to have some manual control over the video settings. I am planning on setting up a web interface to change some settings on the fly. That way, anyone here can tweak things from their tablet or phone.

I have a handful of possible uses for the web interface:

  • Change active video outputs and rotation (while games are running)
  • Adjust volume, toggle ambient arcade sound track
  • Kill the currently running game if it gets stuck
  • Power down the cabinet

A Couple of Useful Snippets from My Shell Config

| Comments

I’ve been slowly and incrementally working on cleaning up my shell config. I’ve been procrastinating over my persist and forget system for quite a while now. I have it up and working here just fine, but I built it and its extra git repository in place. I need to automate the installation and configuration process and I would also like to make sure it isn’t likely to eat anyone’s file before I release it.

In the mean-time, though, I have been digging through my configuration and I’ve found a few gems that I would like to list here. I use these under zsh but I am pretty sure they will work fine under bash as well.

Quickly share files on the public Internet with Python and SSH

I see ‘python -m SimpleHTTPServer’ one liner all the time. By itself this one is pretty useless for me. I almost never need to share something with anyone on my local network. I use this function instead:

My webshare function
1
2
3
4
5
6
7
8
9
10
11
12
webshare () {
  local SSHHOST=patshead.com
  local SSHPORT=9999

  python -m SimpleHTTPServer &
  local PID=$!

  echo http://$SSHHOST:$SSHPORT | xclip
  echo Press enter to stop sharing, http://$SSHHOST:$SSHPORT copied to primary selection
  /usr/bin/ssh -R $SSHPORT:127.0.0.1:8000 $SSHHOST 'read'
  kill $PID
}

This does require you to have a server out on the Internet that you can ssh into. For my purposes, this fills a gap somewhere between a pastebin and something like Dropbox. I use it when I have a handful of files I want someone to take a look at.

A smarter tail command

I lifted this one from commandlinefu.com:

My tail function
1
2
3
4
5
6
7
8
9
10
11
12
13
14
tail() {
  local thbin="/usr/bin/tail"
  local fc lpf thbin

  if [ "${1:0:1}" != "-" ]; then
    fc=$(($#==0?1:$#))
    lpf="$((($LINES - 3 - 2 * $fc) / $fc))"
    lpf="$(($lpf<1?2:$lpf))"

    [ $fc -eq 1 ] && $thbin -n $lpf "$@" | /usr/bin/fold -w $COLUMNS | $thbin -n
  else
    $thbin "$@"
  fi
}

I really like this one. This tail wrapper checks the size of the terminal window and makes sure it shows you just a bit less than a screen full of output. It even takes long lines into account.

Automatically managing a “scratch” directory

This function was heavily inspired by an entry on Marcin Kulik’s blog:

`` bash My function to create a new scratch directory function ns { local cur_dir="$HOME/tmp/scratch/current" local new_dir="$HOME/tmp/scratch/date +‘%s’`”

mv $cur_dir $new_dir mkdir $cur_dir cd ~/scratch echo “New scratch dir ready” }

I’m always creating new scratch directories to work in, so I really liked his idea of creating a function to help manage the process.

I didn’t change his implementation too much. The only real difference is that my symlink never changes. I’m just moving the old, real scratch directory out of the way and putting a new one back in its place.

Improving the Behavior of the cd Command in Git Repositories

| Comments

Most people are probably aware that calling the cd command without any arguments will take you back to your home directory. If you’re anything like me, you probably do this dozens of times each day.

I also end up working in git repositories quite a bit, and when I am working in a git repository I regularly find myself wanting to return to the root of the repository. Most of the time I am not buried too deep and it just takes one or two cd .. commands to climb up to where I want to be.

This seemed a bit silly to me. I’d rather not have to count how many levels deep I am. I decided that it would be a good idea to overload the cd command. Now, if I am in deep inside a git repository and call cd with no arguments, it will pop me straight up to the root. If I am at the root of a git repository or not in a repository at all, it will take the usual action and return me to my home directory.

screenshot of gitcd in action

Here is the code:

git_cd function
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
_git_cd() {
  if [[ "$1" != "" ]]; then
    cd "$@"
  else
    local OUTPUT
    OUTPUT="$(git rev-parse --show-toplevel 2>/dev/null)"
    if [[ -e "$OUTPUT" ]]; then
      if [[ "$OUTPUT" != "$(pwd)" ]]; then
        cd "$OUTPUT"
      else
        cd
      fi
    else
      cd 
    fi
  fi
}

alias cd=_git_cd

Update 2012-11-13: I found more code!

I found another small, helpful shell function that I’ve been using to augment the cd command. I have no idea where this little function came from. It has probably been in my config for quite a long time.

Screenshot of improved gitcd in action

If cd is given an existing file as the argument, this function will change to the directory containing that file. If not, it will just do what cd would normally do. I’m ever so slightly surprised that this function plays nicely with _git_cd!

Here is (very simple) the “cd-to-file” function:

cd to file function
1
2
3
4
5
6
7
8
9
cd () {
  if [[ -f "$1" ]]; then
    builtin cd $(dirname "$1")
  elif [[ "$1" == "" ]]; then
    builtin cd
  else
    builtin cd "$1"
  fi
}

Both the cd function and _git_cd function work using zsh or bash.

(Not Quite) Native Linux Games for an Arcade Cabinet: Mutant Mudds

| Comments

I haven’t played this one much yet. I found this game in the Indie Royale Harvest Bundle, but my Google-fu couldn’t turn up any information on whether or not I’d be able to get it running on Linux using Wine, so I ended up trying it out for myself.

First level on the internal LCD The title screen The introduction

Getting it running under Wine

So far the game is running flawlessly under Wine. It took a bit of trial and error to get it up and running, though. I ended up trying quite a few different versions of Wine before it would work correctly. It ended up working when I tried version 1.5.9. When using versions 1.4.1, 1.5.3, and 1.5.16, it either failed to start or it just showed a black screen.

Knowing that part makes it easy. You just need to use winetricks to install d3dx9 and d3dcompiler_43. I ended up doing all that using Play On Linux. I also threw together my first POL installation script, MutantMudds.pol.

I’m sure it isn’t the most elegant script, but it is easy to use and it works. The steps should go something like this:

  • click on Tools -> Run a local script in the Play On Linux window
  • choose my MutantMudds.pol file
  • click install/ok/next/etc on any DirectX installer windows
  • choose MutantMudds_installer.exe when it asks for the installer
  • click through the Mutant Mudds installer

The controls

Mapping the game controls to the arcade control panel was easy. Mutant Mudds uses the arrow keys to move around, X to jump, Z to shoot, and escape to quit. It is one of those wonderful, arcade-friendly games that don’t require the mouse at all.

Early impressions

When I first saw the (very short) video on the Indie Royale site it made me think of Cave Story. After sitting at the controls for a couple of minutes and getting a better look at the graphics, I’m getting more of a Commander Keen vibe. That’s a very good thing. I have fond memories of playing most of the Commander Keen series.

Update: I just tested Mutant Mudds with Wine version 1.6 and it runs just fine. With any luck it will continue to run on later releases as well.

Mutant Mudds is definitely going to be an excellent addition to the arcade cabinet.

Running Jelly Bean on the Original Samsung Galaxy S (T-Mobile Vibrant)

| Comments

Overall, I like my aging T-Mobile Vibrant, but it has been a bit of a mixed bag. When it debuted, the spec sheet made it look like one of the best devices available. It was thin. It was light. It had a big, bright AMOLED screen. It also had as much or more RAM, CPU, and GPU as any other phone available.

The software it shipped with was ridiculously bad. Samsung’s oddball RFS file system was really, really bad. Software updates were slow and rare. I don’t think T-Mobile got an official Ice Cream Sandwich release…

Support from my favorite aftermarket firmware, Cyanogenmod, was slow and very spotty. The phone also has an absolutely worthless GPS chipset.

I don’t want to imply that the phone was terrible. Team Whiskey gave us pretty good Android 2.1 and 2.2-based firmwares, even if the GPS never worked with them.

One third battery left after 24 hours! Even better, 19% remaining after another six hours

Slim Bean Jelly Bean ROM

Fast-forward to today, and things are looking pretty good. I’ve been running the Slim Bean firmware on my phone since version 2.0 and I’m pretty happy with how the Vibrant is running now.

I should qualify that statement a bit. Last year when I bought a (rather awful) 10” Viewsonic G-Tablet, I started relying on my phone just a bit less. Now that I’ve upgraded to a Nexus 7 tablet I’d be surprised if I use my phone more than an hour during any given week. My phone experience can be pretty bad these days and still be more than acceptable.

That said, I do require decent battery life. Slim Bean is giving me more battery run-time than I’ve ever had with any previous firmware. Stand-by battery time has been particularly amazing, even though my battery is more than two years old. I’ve had days where the phone has been off the charger for over 36 hours and the low battery warning hasn’t gone off yet. Those are particularly low-use days, though.

The screenshot above is from a pretty average day around the house, connected to Wi-Fi the whole time. It does phenomenally well in this case. Even with over an hour of screen time I still had over one third of my battery remaining after being unplugged for nearly 24 hours.

On days with a more normal 50/50 split between Wi-Fi and cell data, the battery drains quite a bit faster. Even then it still has no problem staying alive for 18 hours with a similar amount of screen-on time.

My phone is running Slim Bean 2.8 plus the Semaphore kernel.

Is it stable?

Everything except the GPS seems to be working just fine.

Other than that I can’t complain. Scrolling around within individual applications is noticeably more buttery, but switching between apps is still a slow experience. Using the Nexus 7 every day doesn’t help my feelings about that.

What’s wrong with the GPS?

Turning on GPS causes the phone not to sleep properly any more until it is powered off. It will just eat through battery in a matter of hours, even if you later turn off GPS. This seems to have been a problem on every single firmware I can remember using, probably all the way back to the day I opened the box.

When the GPS is on, it is sometimes able to find some satellites and get a lock. Maybe…

Semaphore kernel tweaks

I am running Semaphore kernel on my Vibrant and I’ve made a few tweaks using the Semaphore Manager app:

  • Changed the I/O scheduler to Simple I/O
  • Enabled Bigmem
  • Set LiveOC to 114%
  • Changed to the SmartAssV2 CPU Governor

Even overclocked to 1140 MHz I am still getting better battery life now than I ever did before.

Update 2013-04-16: Upgraded to Slim Bean 4.2.2

I’ve been happily and lazily ignoring the messages telling me that for months. Slim Bean’s little update manager app kept informing me that there was a minor update, but I was happy with how the phone was running and didn’t think it’d be worth the effort to update.

A couple of weeks ago, a friend was picking on me a bit because my aging Vibrant was only running Android version 4.1.2. I told him that there was no 4.2 release of Slim Bean. A few days later, I learned that I was lying to him.

Updating the phone was a snap. I did not reset the phone. I just flashed the Slim Bean, Google Apps, Google Now, and the latest Semaphore kernel zip files and wiped the cache partition. Nothing terribly weird happened, other than one or two icons on my home screen needed to be recreated.

The upgrade seems to have made my old Vibrant just a bit smoother and faster. It could just be my imagination, though.

Automatically Expanding zsh Global Aliases - Simplified

| Comments

Last year I set up a key binding to automatically expand zsh global aliases as you type. I am definitely not the first person to do this, but I recently discovered a much cleaner way to accomplish the same thing.

globalias demo animation

zsh already ships with a function called expand-alias. I was able to replace the majority of my own code with a call to this existing function. I probably could have almost gotten away with just binding expand-alias to the space bar. For my uses, though, I think this would have been an ugly solution.

I don’t often want to see regular aliases expanded. That would just clutter up my command line too often. I also use the pretty standard practice of using only capital letters in the names of my global aliases. This made it easy to construct a regex as a filter for my globalias function:

globalias code
1
2
3
4
5
6
7
8
9
10
11
12
13
globalias() {
   if [[ $LBUFFER =~ ' [A-Z0-9]+$' ]]; then
     zle _expand_alias
     zle expand-word
   fi
   zle self-insert
}

zle -N globalias

bindkey " " globalias
bindkey "^ " magic-space           # control-space to bypass completion
bindkey -M isearch " " magic-space # normal space during searches

If you’d like to try it out you can just add the above code to your zsh config file, or you can download and source oh-my-zsh plugin.

It should be no problem to loosen up or completely remove the filtering regex if expanding only all-caps aliases isn’t to your liking.

Update: I added zle expand-word to the globalias function. I have one or two global aliases that end in a file glob. This makes them immediately appear expanded.

A Quick Comparison of Gesture Keyboards for Android - 2012 Edition

| Comments

I’ve been using Swype for quite a few years now. I am a really big fan of Swype and I don’t think I would be happy without a sweeping/gesture-based keyboard. I recently learned about a keyboard, called Keymonk, that allows you to gesture with two fingers at once. I’ve been using the free version of Keymonk for almost a week now and I have been mostly happy with it.

Today I installed the stock Android 4.2 keyboard on my Nexus 7. This new version of the default Android keyboard also allows for gesture-based typing.

Swype

I’ve used Swype for a long time and I am very fond of it. Of the three gesture-based keyboards I’ve tried, Swype is definitely the most accurate of the bunch. There are often times when I know that I’ve completely botched up the spelling of a word very, very badly but I just keep going and Swype more often than not guesses exactly what I was trying to input.

One of my favorite Swype gestures is sweeping above the keyboard to capitalize a letter. I try to do this on the other two keyboards all the time.

Swype is currently free but you have to sign up for an account, download their installer, log into their installer, and then finally install Swype. I’d be willing to pay to not have to jump through these hoops every time I get a new device.

Keymonk

Keymonk allows you to use two fingers (likely thumbs) to input words. I’ve had a lot of fun thinking up words like “inconceivable” and “indubitably” to input with both thumbs. It is a little confusing at first but I’m starting to catch on a bit. I might be typing faster with two thumbs now that I do with one finger.

Fortunately, you can use Keymonk one-handed, just like Swype. I also like the way Keymonk highlights the key your finger is currently touching during your gesture. This makes it easy to see when you are overshooting your target.

Keymonk also feels like the fastest of these three keyboards. It pops up much faster than Swype on my old Samsung Galaxy S. It even pops up noticeably faster than either of the other two keyboards on my Nexus 7.

Keymonk’s method of inputting numbers and symbols is superior to Swype. You can still tap shift/numlock and peck away at numbers like with any other keyboard but you can also gesture from the numlock key straight to the desired number/symbol. Punctuation input works in a similar manner.

Since I’m only currently using the free version of Keymonk, I am not able add words to its dictionary. The free version also does not automatically insert a space after punctuation. That bites me a lot because I’m in the habit of Swype doing this for me.

The quick load time, better number/symbol input, and the lack of an annoying installer/updater may very well be worth the four bucks. I think I’d like to see an update or two before I commit to using Keymonk on a more permanent basis, though.

The new Android 4.2 keyboard

The new Android keyboard isn’t bad, but it sure isn’t Swype. It seems to do an even worse job of guessing the correct word out of my random flailing about as Keymonk.

Along with Swype’s capitalization gesture, I find myself very much missing Swype’s “punctuation to spacebar” gesture for quickly inserting punctuation. Keymonk has its own gesture that fills this role.

It is interesting how the Android keyboard prints the partial word that you’ve spelled above your finger and it follows you around as you gesture. I’m not certain how useful that is, though, because my finger moves around pretty quickly. It also gently lights up the key your finger is hovering over, similar to Keymonk.

Which keyboard should I use?

In my opinion, Keymonk doesn’t have far to go to catch up with Swype. I wanted to wait for Keymonk to be updated once or twice before buying it, but writing this post has just about convinced me that the advantages of Keymonk might be worth buying.

Update: Keymonk seems to be dead

I’m pretty disappointed that Keymonk hasn’t been updated in over a year. I still try to use it every once in a while, but it is pretty buggy on newer versions of Android. It will randomly stop responding to gestures and stop suggesting words.

I’ve never actually measured my typing speed with any Android keyboards, but when I use Keymonk it feels like I’m typing much faster. I really miss that.

Cocktail Arcade Cabinet Build: Postmortem - The Things We Got Wrong

| Comments

I’m very happy with the cocktail cabinet that we built. It was a lot of fun to build and it is even more fun to play!

I made a few less-than-optimal choices in the design of this cabinet. I’m not going to call them mistakes (except maybe the choice of monitor). I’ve had a chance to visit an arcade or two since the cabinet was finished. I was worried that seeing a bunch of real arcade machines would make me disappointed in our work.

My feelings while visiting those arcades were actually quite the opposite! In most ways, our cabinet looks much, much better than the majority of real, old-school arcade machines. The most noticeable difference is the lack of artwork on our cabinet. This was our choice and it fits in with everything else in my office much better this way.

Here’s a list of some of the things I might have liked to do differently.

Test fitting joystick under unpainted plexiglas

The buttons are fine, but the joysticks…

When I was shopping for parts, I primarily had the Mortal Kombat series of games in mind. The HAPP joysticks I chose seem very much like what I remember from my days of playing Mortal Kombat II back in high school. They have the right shape and feel. You can even get Raiden to teleport by pulling the stick towards you and letting it fly out of your hand, just like on the real cabinet.

The HAPP joysticks aren’t terribly precise, and the quality of each of the four joysticks I bought varies quite a bit. My player-one controller likes to make an odd clunk when you push it to the left… It will engage the switch, feel like it is at the end of its throw distance, then it will clunk and move a tiny bit more. All of them do this sort of thing some of the time, but not nearly as often as player one.

I haven’t actually played much Mortal Kombat. I’ve spent more time playing modern indie games than I have spent playing actual old-school arcade games. These big, imprecise joysticks with their longer throw aren’t very well suited to anything besides Mortal Kombat and other similar games.

I would definitely choose a different joystick.

Arcade cabinet joystick close up

The table is too tall

I wanted an adult-size cocktail table with a bit of leg room. We got the controller height right—there’s about an inch of knee clearance under the control box when you sit down at the table. I miscalculated on the amount of vertical clearance we needed between the control panels and the glass tabletop.

I was aiming for 5 ½” of clearance. We ended up with 5 5/8” of clearance. That’s 1/8” more than we were hoping for, and that ended up being almost 2” more than is really necessary. That would put the cabinet at a more usable height of 32 inches instead of the 34 inches we ended up with. Most tables and desks are 29 to 30 inches. Our cocktail cabinet is approaching counter top height, which is usually about 36 inches.

If we had to, we could probably squeeze a half-inch or more out of the depth of the control panel boxes, too.

Yardstick included to show scale

Quarter inch glass is a bit thin but it works

I’m very glad that we went with glass. If we went with plastic it would have had to be very thick to be rigid enough to work with our design. To use acrylic we would have had to support it from underneath with wood or particleboard, and that would have made the table even taller.

The quarter inch piece of glass we used was surprisingly inexpensive. Our 32” by 42” piece of glass with rounded corners cost less than $60 from a local shop. A thick enough piece of plastic would have been way more expensive and we would have had to radius the corners ourselves. Definitely check your local glass retailers because this was way less expensive than the glass we were finding on the Internet. All the good Internet prices were on certain pre-cut sizes. We had ours cut to exactly the dimensions we wanted.

The thin glass has made me nervous on more than one occasion. When I saw someone sitting at the end with their elbows on the table and putting a bit of weight on it, I couldn’t believe how much the glass was flexing. With our large surface we probably should have gone with 3/8” glass.

Some buttons are installed

Some molding problems

We have a pair of ninety-degree bends in the t-molding at each control panel. The problem is that there is only about an inch of molding after the bend. You can see it popping out a bit in the above picture. We ended up having to glue some of these small sections in. If I had anticipated this problem I would have eliminated it from the design.

I’m also unhappy that I have one seam where I have a single piece of molding circling the entire cabinet at the control panels. The seam is in the center of the player-four seat, and I currently have that side up against the wall. I don’t like knowing that it is hiding back there, though. Unfortunately, I don’t think I could have designed this one away. That single ring of light blue molding is one of my favorite features of the cabinet.

Close up while applying the sticky-back vinyl

Stick on vinyl…

The sticky-back vinyl looks and feels great. In my opinion, it is too expensive and it is much too time consuming to apply it. Due to the high shipping costs, the vinyl was over 20% of the total cost of the cabinet (and I almost goofed up; we barely had enough to cover the cabinet).

It also took a very long time to cover the cabinet. The cabinet build took us a very large number of hours. I think if we did it again, most of the steps would take half the time, but not on the vinyl. You have to be very meticulous when you put it on, and trimming all the edges perfectly takes a lot of time.

I would like to try using melamine board on the next cabinet. It is only a bit more expensive than particleboard, but even if we had to paint it we’d save a ton of time compared to using vinyl.

Finished cabinet with the lid off

Choose the right display

I already wrote about the problems with my choice of monitor, it only has a good viewing angle from three sides. If I build another four-player cocktail cabinet I will probably use a 26” or 32” LCD television. However, because of the asymmetric vertical viewing angle of an LCD monitor we are probably getting a better view right now at the player-three seat than we would with even an IPS display.

I’m not sure if I would build another four-player cabinet. Most of the time we play one or two-player games. With the size of our table it is more convenient to play single player games from the player one seat with the screen split with MAME’s cocktail mode.

Outside of MAME and MESS, this isn’t an option. All the other games have to face the player three seat. This means that all native games are effectively limited to one player.

A trackball would have been useful…

I really should have included a trackball. I thought it would be a bad idea to put one underneath a sheet of glass and in such a small, enclosed space.

I’ve been playing more native games on the cabinet than emulated games. Most native games require a mouse for something, even if it is only to start a new game. I’ve been doing a reasonable job cheating at this, but it is a pain in the neck.

Shell Environment Upgrade and Cleanup: Part 2 - Migrating from oh-my-zsh to Prezto

| Comments

My migration from oh-my-zsh to Prezto actually began quite some time ago, and I accidentally made things much more complicated than they needed to be. I was completely switched over while Prezto was still a fork of the oh-my-zsh github repository. At some point in time, Prezto was moved to its own repository.

I happened to not be paying attention at the time, and my local copy of Prezto got way out of sync. Merging was going to be quite a headache. This seemed to be the perfect time to start fresh and only move what I actually needed from the old repository to the new.

Migrating oh-my-zsh’s custom directory to Prezto

I currently have 16 scripts that were in my ~/.oh-my-zsh/custom directory. They’re mostly bite-sized, ranging in size from a single line up to a few dozen. I took the lazy way out here and created a Prezto module called custom.

Useless little screenshot of Prezto for zsh

I moved all my scripts from ~/.oh-my-zsh/custom/ to ~/.zprezto/modules/custom/scripts and created an init.zsh to loop through and sort them all.

init.zsh:

for file in /home/wonko/.zprezto/modules/wonko/scripts/*.zsh; do
  source $file
done

It is pretty simple but it is getting the job done.

Next step: Persistence of config files

I already wrote a small persistence module that I’m using but it is only just barely half-baked at this point. I have a basic persist command to automatically store files in a git repository and I have a forget command to restore them to their previous state.

They work, but their error handling still needs work. I’d hate to release this and have someone lose a file because of a stupid bug.

It also still needs a higher-level command to globally restore all the persisted data on a new system. A command to revert all persisted files back to normal files wouldn’t hurt, either.

I haven’t been working on this part at all. I got too distracted working on zsh-dwim. zsh-dwim is quite a bit more interesting and, for right now, I’m much more excited about it!

Cleanup of zsh-dwim

| Comments

I went ahead and cleaned up zsh-dwim (Do What I Mean) quite a bit. If you haven’t been following along, zsh-dwim attempts to predict your intended next command when you hit control-u. I also recorded a short screen cast demonstrating some of what happens when you hit control-u.

Removing the Perl dependency

I decided that I may as well bite the bullet and move all the transformation logic to zsh from the original Perl “helper” script. Early on, I was worried that zsh code would be too ugly, but I have too many ideas that would be hard to implement with the code base split up like that.

All the transformation logic now uses zsh and sed. I was hoping to use zsh’s built-in substitution abilities, but they were lacking some important features. The “scp to mv” transformation looked like it would have been really ugly without sed.

Cleaning up the if/then spaghetti

When I was testing this idea I only had two transformations, so a pair of if/then statements didn’t seem like a problem. Now that there are ten, it is starting to get ugly.

I ended up moving all the transformation definitions into a zsh hash and I created a little helper function to add new definitions to that hash. When you call zsh-dwim, it loops over that hash testing for relevant transformations. This means we can now add transformations anywhere in our shell configuration.

Adding a transformation looks like this now:

  _dwim_add_transform '^mkdir ' \
    'BUFFER=$(echo $BUFFER | sed -re "s/^mkdir /cd /")'

What’s coming down the road?

There’s still a lot of repetitive nonsense to eliminate. I need to factor out all those “BUFFER=$(echo $BUFFER | … )” bits. They’re repeated in every single transformation.

I’d also like to make use of more data in deciding which transformation to run. For instance, it might only make sense to call ssh-keygen if the ssh command fails.

The zsh-dwim repository is ready to be pulled into Prezto as a git submodule. It can probably be used as a plugin with oh-my-zsh pretty easily, and the init.zsh file can probably be sourced right into plain old zsh without, hopefully, any problem at all.