Wednesday, November 26, 2014

Useful things I carry in my laptop bag

I never know what I will need when I am visiting a location I am not familiar with. Over the years, I have settled on bringing along a default set of "things I shouldn't have to remember to bring along, but I do anyway ;-)"

Just a heads up: The links below include Amazon affiliate codes, which means if you make purchases after following those links, you will be supporting this blog.

You are in a meeting room, with a nice giant display. You have something you want to show the six people in the room. While the figure might look ordinary on your 13" laptop's screen, it would really impress everyone in the room if they could just see it on that large screen. Who knows, maybe the grumpy person sitting at the far corner of the table might even join in on the conversation.

But, and it seems there is always a but, the administrative assistant who has the key to the cabinet which holds the RFID card which opens the drawer which houses the incredibly precious extra display cables is nowhere to be found. And, because those display cables for visitors are so precious, nobody else can open the cabinet which holds the RFID card which opens the drawer which houses the extra display cables.

Only, this time, you are prepared. While HDMI is becoming more and more common in conference rooms, I still encounter classrooms and auditoriums with just VGA port available to connect to the projections system. Then, of course, there is network connectivity. If you have a one hour meeting, and the first 20 minutes is spent trying to get your computer hooked up to a display, and get online, that meeting is already lost.

So, these are the connectors I always bring with me:

Apple Mini DisplayPort to VGA Adapter MB572Z/A: This is for my mid-2010 13" MacBook Pro. Your Apple product probably uses some other connector. I am not up-to-date on the display adapter varieties used throughout their product line, so double check first. I just have to say, this came in extremely handy many times. You may want to also look at Apple Mini DisplayPort to VGA Adapter MB572Z/B to make sure you have the right one.

Of course, it is not enough to have the converter. You don't want to end up in an awkward situation because you have to stay close to the connector. That's when the Cables Unlimited PCM-2240-06 SVGA Cable comes in handy. This one at 6 ft long is just long enough to be handy while keeping the weight in check. It also has a standard audio cable which you don't need very often, but when you do, it is a life saver.

My go-to laptops, being the "ancient" machines they are, all have built-in Ethernet adapters (one of them even has a modem that works in Linux ;-) But, I like having the UtechSmart USB 2.0 to 10/100 Ethernet adapter just in case I am working with someone who only has USB and wireless. It's good to save the day like that. Of course, I actually carry around spare network cables as well.

It is always good to be able to connect to HDMI displays, if only to watch free Amazon Prime movies in your hotel room. So, I also carry around Tera Grand's Premium Mini DisplayPort to HDMI Adapter Cable with Audio Support (yes, I am a cheapskate), and an HDMI extension cable to go along with that.

Every now and then, I check out cheap USB flash drives, and stuff one or two extra in my bag, just in case. While it is not the greatest format for data safety, exFAT is extremely convenient in that almost all reasonably recent operating systems support it, and it gives you files sizes greater than 32GB. Just be cautious, and don't let your computer go to sleep while accessing it. In principle, a reasonable operating system should not let anything bad happen in that case, but my MacBook Pro messed up my Mushkin Ventura Pro 64 GB Flash Drive that I had to contact tech support (something I very rarely do), and some special software to re-initialize it.

It's good to have a blank USB drive so as to prevent someone else's filesystem monitor from accessing your files for another client. Keep in mind that plugging flash drives into other systems is inherently dangerous. There are some precautions you can take, but, I do not know how to protect against hardware level malware short of never using USB flash drivers, but, I don't think anyone does either, but I do like to have my own blank drive, initialized in Linux with me, and if my drive has been connected to another computer, I like to check it out first in the same environment, copy the file over inside that environment. This method provides reasonable protection against software based malware, but, if I were to ever receive a flash drive with builtin hardware based malware from Amazon, I would never know it. Such is life. Until recently, I had no clue such a thing was even possible.

For those times, I do carry around with me another drive with ArchLinux installed on it.

Finally, I do love cool pens, so I always have a lot of pens with me. But, for thinking, nothing beats your standard pencil. Mechanical pencils are too annoying, especially when doodling, which means I also have a good pencil sharpener. Complete the set with the best eraser of all time. It is also useful when you need to clean memory card contacts.

The one thing I really want is a decent modem I can use from Windows, OS X, and ArchLinux, for those times I need to fax something while on the road, but I do not leave a copy in some random fax machine at a hotel business center or UPS location. Any recommendations?

HICKIES

I forgot about the most important thing: HICKIES Elastic Lacing System. One time, half way through a particularly long string of flights, disaster-struck. No, I am not referring to the belly landing. After the umpteenth security checkpoint, the laces on one my shoes just broke. Having packed light, these dress shoes were the only ones with me, and I wasn't carrying any spare shoe laces. I might be hallucinating, but I believe there used to be a time you could find a pair of shoe-laces at a decent-sized international airport. Apparently, those days are long gone. Luckily, a Brookstone store had a box of HICKIES in assorted colors, including a set of dark grey and black. I ended up keeping them on my shoes for the entire week I was working on site, and no one noticed that my dress shoes did not have proper laces.

They are a little looser than regular laces, but they do make going through security checkpoints a breeze. Of course, I put regular laces on the moment I got a chance to pick a pair, but now I do have a box of HICKIES as a backup plan.

Friday, November 21, 2014

Use Windows' text to speech API from your Perl script

Jonathan Stowe commented on Facebook:

I hate say in any computer language that doesn't actually make audible speaking sounds.

Well, you can use Windows' text to speech API from Perl:

#!/usr/bin/env perl

use 5.020; # Why not?!
use strict;
use warnings;

use Win32::OLE;
$Win32::OLE::Warn = 3;

my $speaker = Win32::OLE->new('SAPI.spvoice');

while (my $line = <DATA>) {
    next unless $line =~ /\S/;
    $speaker->Speak( $line );
}

__DATA__
Flexible & Powerful

That's why we love Perl 5

Visit Perl.org

Now, if you want to replace the builtin say, I am afraid you are stuck. But, even with the use 5.020; line, you could add a no feature 'say';, and define your own say function.

Additionally, the speech API understands some XML directives.

Perl6 UTF-8 output in cmd.exe on Windows 8.1

Back in May, starting with UTF-8 output from Perl and C programs in cmd.exe on Windows 8, I wrote a few posts summarizing my bewilderment with extra bytes appearing in UTF-8 output from perl when cmd.exe codepage was set to UTF-8 via chcp 65001.

The same problem still exists with the perl 5.20.1 I built recently.

So, I decided to see what perl6, using MoarVM, can give me.

In the same cmd.exe Window, I typed:

C:\Temp> perl6 -e "Buf.new(0xce, 0xb1, 0xce, 0xb2, 0xce, 0xb3, 0x31).decode('UTF-8').say"
αβγ1

or, in a script:

use v6;
'αβγ1'.say;

which gave me the output:

αβγ1

It may not seem like much, but remember that the Perl script:

use utf8;
use strict;
use warnings;
use warnings qw(FATAL utf8);

binmode STDOUT, ':utf8';

print 'αβγ1', "\n";

outputs

αβγ1
1

Let's see now:

.say for (
    "Hava karlı",
    "Bu iş kârlı",
    "İstanbul",
    "Yağ yağ yağmur");
Hava karlı
Bu iş kârlı
İstanbul
Yağ yağ yağmur

And, then,

say "karlı" eq "kârlı";
False

which means perl6 understands the difference between snowy and profitable.

Of course, so does perl5 ... but, when it comes to printing, it has issues:

use 5.020;
use utf8;
binmode STDOUT, ":utf8";

print for "karlı", "kârlı";

gives the output:

karlıkârlılı�

Monday, November 17, 2014

TDD is all well and good, but who's testing the tests?

While working on my patch to Module::Install, I happened to do another cpanoutdated | cpanm -v for my shiny new Perl 5.20.1 build. This pulled in Test::More, with another one of those file path interpolation into regex pattern problems:

Here are the relevant parts:

Unrecognized escape \M passed through in regex; marked by <-- HERE in m/The new sub is 'MyModernTester::__ANON__' defined in t\Behavior\M <-- HERE onkeyPatching_diag.t

Got: The new sub is 'MyModernTester::__ANON__' defined in t\Behavior\MonkeyPatching_diag.t around line 19.

Expected: (?^:The new sub is 'MyModernTester::__ANON__' defined in t\Behavior\MonkeyPatching_diag.t around line 19)

This is not the only instance of this type of test failure.

Please, please, use quotemeta.

Here is the pull request. It consists solely of replacing qr{ … $file … } with qr{ … \Q$file\E … }.

Friday, November 14, 2014

Who put an extra CR in my CRLF? Fun with PerlIO layers

So, playing with my shiny new toy while waiting for remote SAS jobs to finish, I ended up trying to install PerlIO::via::gzip which pulls in PerlIO::Util. PerlIO::Util failed some of its tests, specifically, one relating to PerlIO::tee.

Some of the failures involved an extra 0d before a 0d0a

These failures were perplexing to me, but, at least CPAN testers showed me that I was not alone.

On the other hand, looking at that list, there are clearly Perl installations on Windows where this does not happen. I have been unable to figure out the underlying cause, but I suspect it is at least somewhat related to the series of puzzled posts I made about UTF-8 output from perl in a cmd.exe Window.

I went ahead, and force installed PerlIO::Util just 'cause I am lazy, and I wanted to use PerlIO::via::gzip. Here is a short script to start with. We are printing to scalars:

#!/usr/bin/env perl

use 5.020;
use strict;
use warnings;

use PerlIO::Util;

open my $f, '>:tee', \(my ($x, $y))
    or die "tee open: $!";

binmode $f, ':crlf' or die "binmode: $!";

print $f "\n";

close $f;

say hexdump($_) for $x, $y;

# Thanks for the tip in the comments
sub hexdump { sprintf('%*v02x', ' ', $_[0]) }

And, the output is:

 t.pl
0d 0a
0d 0a

or

 t.pl | xxd
0000000: 3064 2030 610d 0a30 6420 3061 0d0a       0d 0a..0d 0a..

But, if I do this:

#!/usr/bin/env perl

use 5.020;
use strict;
use warnings;

use PerlIO::Util;

open my $f, '>:tee', 'x', 'y'
    or die "tee open: $!";

binmode $f, ':crlf' or die "binmode: $!";

print $f "abc\n";

close $f;

I get:

 xxd x
0000000: 6162 630d 0d0a                           abc...

 xxd y
0000000: 6162 630d 0d0a                           abc...

That is, it looks like the "\n" above gets translated to CRLF, and then another layer translates the last LF to CRLF again.

It seems to my untrained eye that whatever is happening is probably happening within this function in PerlIO-Util.xs:

if(tab && tab->Open){
  f = tab->Open(aTHX_ tab, layers, i,  mode,
    fd, imode, perm, f, narg, args);

  /* apply 'upper' layers
     e.g. [ :unix :perlio :utf8 :creat ]
                          ~~~~~        
  */

  if(f && ++i < n){
   if(PerlIO_apply_layera(aTHX_ f, mode, layers, i, n) != 0){
    PerlIO_close(f);
    f = NULL;
   }
  }

 }

A quick inspection seems to verify this. Here is the list of layers before the application of the :crlf layer:

---               
- unix            
- ~               
- - CANWRITE      
  - OPEN          
  - TRUNCATE      
---               
- crlf            
- ~               
- - CANWRITE      
  - FASTGETS      
  - CRLF          
  - TRUNCATE      
---               
- tee             
- y               
- - CANWRITE      
  - FASTGETS      
  - CRLF          
  - TRUNCATE

and, here is the list of layers after the binmode $f, ':crlf':

---            
- unix         
- ~            
- - CANWRITE   
  - OPEN       
  - TRUNCATE   
---            
- crlf         
- ~            
- - CANWRITE   
  - FASTGETS   
  - CRLF       
  - TRUNCATE   
---            
- tee          
- y            
- - CANWRITE   
  - FASTGETS   
  - CRLF       
  - TRUNCATE   
---            
- crlf         
- ~            
- - CANWRITE   
  - FASTGETS   
  - CRLF       
  - TRUNCATE

I have demonstrated in the past that I don't necessarily understand PerlIO layers very well. But, perldoc PerlIO says:

:crlf

A layer that implements DOS/Windows like CRLF line endings. On read converts pairs of CR,LF to a single "\n" newline character. On write converts each "\n" to a CR,LF pair. Note that this layer will silently refuse to be pushed on top of itself. (emphasis mine)

Any ideas?

Thursday, November 13, 2014

Compile Vim and OpenSSL with Visual Studio 2013 Community Edition

They both build fine. For OpenSSL, follow the instructions at Building OpenSSL 1.0.1g on 64-bit Windows Pro 8.1 with Windows SDK 7.1. For Vim, refer to Building and Installing gVim on Windows 8.1 Pro.

Since 7.4.393, you can build GVim with DirectX support on Windows Vista and later. Subjectively, things look much better to me.

If you run into problems with Vim, make sure Windows SDK 7.1 is installed, and add its include directory (and only the include) to your header search path (for Win32.mak):

set INCLUDE=%INCLUDE%;C:\Program Files\Microsoft SDKs\Windows\v7.1\Include

The correct include path to point to the SDK included with the VS2013CE would be:

C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include

Again, this is just for the Win32.mak file, so it doesn't make a huge difference, but, still.

After building OpenSSL, you can do:

set OPENSSL_PREFIX=c:\your-openssl-top-dir
cpanm LWP::Protocol::https

That reminds me, I should support OPENSSL_PREFIX in Crypt::SSLeay as well.

On my system, a test in t\io-socket-ip.t fails for a reason I cannot figure out. It may have to do with peculiarities of my system, so I force installed IO::Socket::SSL.

Wednesday, November 12, 2014

You've gotta quotemeta!

Seriously, if you are going to interpolate a filename into a string that is to be used as a regex pattern, you must use quotemeta. That is, just surround the filename with \Q and \E. It doesn't take much, but it does prevent unforced errors.

So, after building my shiny new Perl 5.20.1 with the Community Edition of Visual Studio 2013, I did a:

C:\Users\user> cpanm Moo Template Mojolicious

After a few minutes, I looked, and saw that a bunch of dependencies had failed to build.

First to catch my attention was Test::LeakTrace — odd because the test files giving the problems were written more than five years ago, but I didn't run into this problem with any of the previous times I installed the aforementioned modules. … A-ha! Template Toolkit started checking for leaks.

What are these tests that are failing in Test::LeakTrace? Glad you asked. Here is one:

like __FILE__, qr/$si->[1]/, 'state info'
    or diag(Dumper \@info);

And the others are here, here, here, and here.

Yeah, sure, I am going to put together a patch … but … seriously?!

PS: Rather curiously, Test::Fatal also fails tests. See if you can spot the reason:

#   Failed test '$TODO works'
#   at t\todo.t line 110.
# STDOUT is:
# not ok 1 - succeeded # TODO unimplemented
# #   Failed (TODO) test 'succeeded'
# #   at t\todo.t line 108.
# #          got: '0'
# #     expected: '1'
# ok 2 - no exceptions # TODO unimplemented
# ok 3 - level 1 # TODO unimplemented
#
# not:
# not ok 1 - succeeded # TODO unimplemented
# #   Failed (TODO) test 'succeeded'
# #   at t/todo.t line 108.
# #          got: '0'
# #     expected: '1'
# ok 2 - no exceptions # TODO unimplemented
# ok 3 - level 1 # TODO unimplemented
#
# as expected

Now, this file also has not changed in a long time. Presumably, the way the filename is formatted for the failure message changed recently, but I am not in the mood for a long, uncertain git bisect session.

Of course, the solution to this problem has nothing to do with quotemeta, but I just could not bring myself to put together another blog post.