Tuesday, December 19, 2017

Bulk rename files in Emacs

Here's a problem I recently encountered at work which Emacs solved quite effectively with wdired-mode.

I had a large directory tree of Javascript files that I bulk-converted from coffeescript to ES6. The files originally had the extension ".js.coffee," but after conversion they all became ".js.js". Well, a ".js.js" file extension is absurd, right? How can I rename them all to a more sensible ".js"?

Easy -- use Dired mode to display the files, and then switch to 'wdired" (writeable-dired). String-replace the extension, save -- done and done.

But how to list all files from all subdirs in a single Dired buffer for string replacing? In Dired, subdirs can be "included" in the listing by typing 'i' when your cursor is on the subdir, but this is a pain for more than a couple of includes. After searching a bit, I cam across this bit in the Emacs docs for Dired:

The simplest way to include multiple directories in one Dired buffer is to specify the options ‘-lR’ for running ls. (If you give a numeric argument when you run Dired, then you can specify these options in the minibuffer.) That produces a recursive directory listing showing all subdirectories at all levels.

That is, "C-u 1 C-x d" to launch Dired, choose the parent dir, and then type "lR" in the minibuffer prompt for ls options. Voila! All the subdirs listed in your buffer. Now switch to wdired mode ("C-x q"), then query-replace the string ('M-%'). "C-c C-c" to save the buffer. Done.

I don't think there's an easier way to do a bulk rename.

Monday, March 20, 2017

The Trouble With Mail Attachments in Rails

I ran into a problem with a Rails ActionMailer at work recently, and I thought I'd share my findings. Attachments require a multipart mail message -- but adding an attachment does not cause the message to be multipart.

So I had an HTML-formatted email that was working just fine. The Mailer basically looked like this in the action, with only an .html template was in the views directory.

 class DdosReportMailer < ActionMailer::Base  
  layout 'layouts/mailer'  
  def daily_report(rcpts:)  
   mail(  
    to: EnvVar.get('NOREPLY_EMAIL'),  
    from: EnvVar.get('NOREPLY_EMAIL'),  
    bcc: rcpts,  
    subject: I18n.t("ddos_report_mailer.daily_report.heading")  
   )
  end  
 end  

My story required that I add attachments, but the Rails guide is not exactly clear about when and where to call the 'attachments' method. First, I tried calling it on the mail instance after it was created:

 class DdosReportMailer < ActionMailer::Base  
  layout 'layouts/mailer'  
  def daily_report(rcpts:, reports:)  
   mail(  
    to: EnvVar.get('NOREPLY_EMAIL'),  
    from: EnvVar.get('NOREPLY_EMAIL'),  
    bcc: rcpts,  
    subject: I18n.t("ddos_report_mailer.daily_report.heading")  
   ).tap do |m|  
    reports.each { |k,v| m.attachments[k] = v }  
   end  
  end  
 end  

In the Rails previewer, this looked good. HTML formatting, check; attachment, check. Tests which verified the mail body and attachments passed, so I figured the work was done.  

But when I sent the actual mail, it looked like this:


I immediately lay this problem at the feet of the MailSafe gem, which we use to prevent outbound mail in staging. The MailSafe modification seems so close to the attachment boundary, it must be causing a parsing error! Not to worry -- in production, we won't have this problem. Just to be sure, I whitelisted the original recipient address so there was no MailSafe intervention. Surprisingly, that did not help. 

I went back to the Rails guide and decided the 'attachments' call should be sent to the mailer, not the mail.

 class DdosReportMailer < ActionMailer::Base  
  layout 'layouts/mailer'  
  def daily_report(rcpts:, reports:)  
   reports.each { |k,v| attachments[k] = v }  
   mail(  
    to: EnvVar.get('NOREPLY_EMAIL'),  
    from: EnvVar.get('NOREPLY_EMAIL'),  
    bcc: rcpts,  
    subject: I18n.t("ddos_report_mailer.daily_report.heading")  
   )
  end  
 end  

Now the delivered message looked even worse! Something is wrong with the message parts.


After a bit of Googling I found a discussion about a similar multi-part problem that was solved by passing a block to the 'mail' method and using the format object which is yielded. This did the trick. Although attachments require a multipart message, adding an attachment does not cause the message to be multipart. Using a format block will. Here is the final code.

 class DdosReportMailer < ActionMailer::Base
  layout 'layouts/mailer'
  def daily_report(rcpts:, reports:)
    reports.each { |k, v| attachments[k] = v }
    mail(
      to: EnvVar.get('NOREPLY_EMAIL'),
      from: EnvVar.get('NOREPLY_EMAIL'),
      bcc: rcpts,
      subject: I18n.t("ddos_report_mailer.daily_report.heading")
    ) do |format|
      format.html { render 'daily_report' }
    end
   end
  end

Wednesday, January 25, 2017

Emacs and The Lisp Keybard

I've been using Emacs for my day-to-day developer work for over a year now. I love it, but I do sometimes get a sore left pinky (aka, "Emacs pinky") from hitting the Control key so much. It's not nearly as bad as the mouse-hand tendonitis I used to get from all the clicking in a windowed development environment, but still.

Well it turns out that Emacs' heavy reliance on the control key is explained by the "Lisp keyboards" of the 80s, which influenced its early development. Control is next to the spacebar, where you can hit it with your thumbs.


If you use Emacs, Control is supposed to be big, right next to the space bar. On Windows keyboards, that's typically where the Alt key goes now. Macs put the Command key there. It's time for some key mapping.

I spend about half my day on Macbook Pro docked with a Windows keyboard, the other half using the laptop keyboard on the go. The modifier keys are crazily different, but luckily System Preferences > Keyboard > Modifier Keys lets you pick different mappings for your different keyboards. So I've been trying to get used to this setup:



Whichever key is next to the space bar is now Control, next comes Alt (Meta), and furthest is Super/Command/Windows. CapsLock is an extra Control key, for good measure.

Outside of Emacs, it's going to take some getting used to -- esp. Cmd-C/V, Cmd-Space, Cmd-Tab, the combos I use all the time on the Mac. On the plus side, copy and paste is more compatible with Windows/Linux key combos for copy/paste, where I was already used to "Ctrl-C" with a pinky.

Inside Emacs, using the thumb for Control feels a whole lot better. Control-X O, Control-X G, etc -- I use those constantly, and the thumb just works a lot better. I recommend it!

Monday, March 07, 2016

Learning Emacs, or: Teaching an old dog old tricks

I decided to learn Emacs late last year, and it took some doing. But Emacs in a terminal is now my go-to editor. Why on earth, you might ask.

I've been a professional developer for quite some time, and I've always used IDEs for my work, especially in Java -- Jbuilder, Netbeans, IntelliJ, and, more recently, Rubymine. There are many things to love about these tools: autocompletion, instant symbol navigation, and so forth. Start typing a method call, and the editor prompts you for the parameters by name. Command-click on a symbol and it takes you to the definition, no matter where in the project it may live. But with the power come some annoyances, too. Mysterious freezing, slow start-up time -- and the nagging feeling that maybe I'm outsourcing a bit too much of my knowledge and skill to the IDE.

As a Ruby developer these last few years, I've found myself more and more on the command line. Pry, in particular, made me want to leave Rubymine behind. It's a much more intuitive debugging paradigm, and as far as I can tell, it is completely incompatible with a Rubymine run/debug config. (A 'binding.pry' encountered in the code will just hang the server started in Rubymine.) I wanted to stay in the terminal, where things are always fast and efficient.

It was time to learn Emacs or vi. I decided on Emacs mainly because vi's editing vs. navigation modes have always kind of bothered me.

Some reasons to learn Emacs, in no particular order:
  1. Adios, trackpad and right-click menu navigation. Your hands stay on the keyboard
  2. Learn the Emacs key bindings and you can use them all over MacOS 
  3. Gain a new fundamental skill while doing exactly the same old thing at the job
  4. Get IDE-level productivity on a remote system via SSH
  5. Earn maximum old-timer street cred!
Out of the box, Emacs has some pretty cool stuff to offer. There's plenty to learn if you start with a vanilla install. To name just a couple of things I really like:
  1. Buffers and windows just seem to work better than the typical paradigm (tabs) for dealing with files in a modern editor. C-x b enter always takes you to the previous file, whereas in Rubymine, Sublime, etc, I'm always searching for that other tab I was just using. C-x 3 to split into vertical windows, C-x 1 to get your current frame back to one window. These come in handy -- two files is about all I ever want to see at one time.
  2. Dired for browsing/manipulating files. It's more powerful for file management than the project trees in the modern editors.
Add these packages, and you'll be flying.
  1. Helm and projectile for navigating the project
  2. Magit for git

Learning Emacs is like learning piano (if piano only took a couple of months to learn). It takes time, but you form muscle memory for executing an intention (going to a file, committing changes, etc), which ultimately feels more fluid than poking around in menus and panels with the mouse. Your visual cortex can stay focused on the high-level problem, and your spinal cord takes care of the details.







Tuesday, July 21, 2009

fun with dataphone emulators

So I'm working on a dot-net project right now, and we are supporting mobile devices. I figured I would just download some emulators for iPhone, Android, etc, and check out how things look.

First stop, Apple. Here, the only way to get the iPhone emulator is to download the entire 2.08 Gigabyte SDK after creating a developer account. I'm not very interested in either of those things, so I figured it would be easier to just find someone with an iPhone when we get it on a public server.

The Android SDK is much easier to obtain (only 186 Megabytes, no account required). After reading up on how to start the emulator, I found it will not connect to our internal servers by name or IP. Another failed attempt.

Moving on, I was happy to see Visual Studio has a bunch of Windows CE device emulators bundled. But try to enable "networking" for the emulated platform, and you'll get a message saying that Virtual PC is required, with a download link. That's right, Microsoft device emulators in Visual Studio cannot simulate a network connection without installing Virtual PC 2007. Again, I am not interested.

Why is this so difficult? Why not separate the emulators from SDKs for download? Why not write them to use the host OS networking transparently?

Tuesday, January 20, 2009

The Inauguration, Power, and Consent

I just watched the inauguration and, like many others, I was moved to tears. I've generally been a little skeptical of Obama-mania, but he is the right person for the job, without question. His eloquence, confidence, and humility are truly remarkable.

But I want to comment on how many times I heard the commentators assert amazement at the "peaceful transfer of power" that the inauguration represents. They are astounded that our leaders cede power without violence. But is a violent refusal to yield power even within the realm of possibility? Isn't "peaceful transfer" pretty much standard for most of the world nowadays? England, Canada, El Salvador, etc etc, all see peaceful transfers these days.

In fact, I suspect we are being exposed to a propaganda assertion: "consider yourselves blessed and lucky that these people rule over you peacefully, without infighting." The comradery displayed between these potentially violent adversaries (Clinton and Bush Sr. smiling and hugging, Gore and Bush Jr. sharing a stage) confirms that familiar critique of American two-party politics: these are just two sides of the same coin, a single oligarchical class. Don't mistake me, there are real and profound differences between Republicans and Democrats, and I am very grateful that Obama is president. But everyone on that inauguration stage clearly belongs to the same club.

What else is happening on that stage? The tooting horns, the bunting and banners, the processional entrance -- it's just a good old fashioned pagaent, used by rulers throughout history to impress their majesty and power. The subjects / constituents are always taken right in.

Tuesday, August 05, 2008

Lazy software development!

A colleague commented to me once: you want to look in your server room and see your sys admin relaxing -- feet on desk, leafing through a magazine. If he or she appers busy, stressed, or frantic, you know there's a problem.

The good system administrator sets up the network for maximum automation and minimum human intervention -- scripts do the work, not the ass in the seat. If you're a manager, don't feel cheated if the admin works short hours, feel blessed -- you've got a good one.

I propose that the same is true for coders. Good programmers should opt for the easiest, least complex solution to a problem, and then kick back with a magazine. If you manage developers and see them coding late, or see them stressing out, you know there's a problem. If the system is designed for simplicity and ease of development, feature development should be swift and pain-free.

In other words, Keep It Simple and Do not Repeat Yourself, and you can work bankers' hours. There's a nice side benefit, too: the system will be simpler to understand and maintain.

So here, then, is a Lazy Software Developer Manifesto.

Whereas we have worked on many projects and seen many different methodologies: waterfall, agile, and everything in between;

Whereas these project management styles often produce burned-out workers and bad software;

Therefore, we propose Lazy Methodology.

Here are some initial prececpts:
  1. solve problems using the fewest lines of code / configuration
  2. embrace the old 80/20 rule (focus on your core use cases; skip the outliers that consume huge amounts of time)
  3. only have meetings when you have a reason to
Just the tip of the iceberg. What else?