Archive for Quick tip

One thing cmd.exe is better at than *nix shells (with default configuration)

I know the statement might be considered controversial. I even encourage you to try to prove me wrong, because I wish I knew better solution.

In my every day work I tend to use command prompt a lot. I have both cmd.exe and bash (from Git for Windows) opened all the time. My typical environment comprises numerous directories, I mean more than one hundred. Many of them share parts of their names. The names are long, dozens of characters. I have to move between them over and over again. The problem is that it is not feasible to type longish directory name many times manually.

Now, let’s suppose we have the following (shortened, of course) subdirectories structure of a directory which we are in at the moment:

..
aa
bbaa
ccaadd
eeaaff

When I would like to change the directory to bbaa in cmd.exe I type cd *aa* <Tab> <Tab>, I get the second result of auto completion, I press <Enter> and I have moved to bbaa. If I press <tab> three times, I get ccaadd. And when I press <tab> four times, I get eeaaff. This feature is brilliant. The auto completion works with wildcards and matches not only beginnings of a name. Last, but not least, it allows to cycle through suggestions while in-line editing a command.

The most important part here is: not only beginning of a name (which is, as far as I know, the behavior of a typical Unix shell) AND also ability to have the suggestions inserted in place, not only displayed them below the command prompt.

A Unix shell also does match wildcards, but only displays matched names. It does not offer (or I am not aware of it) a way to instantaneously pass matched name to a command. It only lists relevant suggestions and a user have to then manually re-edit the command so that it has desired argument. cmd.exe is better in that it allows a user to cycle through suggestions while in-line editing command argument. Which is great when it comes to long names of which only some parts can be conveniently memorized by a human.

I propose the following function which could be appended to .bashrc.

function cdg() { ls -d */ | grep -i "$1" | awk "{printf(\"%d : %s\n\", NR, \$0)}"; read choice; if [ "$choice" == "0" ]; then : ; else cd "`ls -d */ | grep -i \"$1\" | awk \"NR==$choice\"`"; fi; }

It is a simplistic function that searches through ls results with grep, parses them with awk and finally picks one of them and calls cd.

Now we can type cdg aa and we get all possible choices:

1 : aa/
2 : bbaa/
3 : ccaadd/
4 : eeaaff/

We simply type the number and we are done being moved to the desired directory. Without the need to manually re-enter the cd command with proper argument. Obviously, in cmd.exe we get this nice auto completion for every command typed in the interpreter, and my solution only solves changing directory use case in bash.

2014.02.02 UPDATE 1: After some deeper research, it turned out that the behavior of cmd.exe can be achieved in bash as well. The following line should be included into .bashrc:

bind '"\t":menu-complete'

However, my solution still serves the purpose as it uses grep -i which makes it case insensitive and thus renders it useful.

2014.02.06 UPDATE 2: I have experienced the second reason my solution is still relevant. It is much faster than pressing <tab> and waiting for the shell to suggest names. This can be observed in an environment with number of directories greater than a few, where MinGW tooling tends to be slow in general.

Python script executed by cron crashes when printing Unicode string

I have written a little Python script for my personal purposes and scheduled it to be run on Raspberry Pi by cron. After some polishing work I was pretty sure it worked well and was successfully tested. What I mean by to be tested is to be executed manually from the shell and to observe the expected results. So far so good.

However when the script was run by cron, it failed at the line where it prints some string containing Unicode characters. The line executes normally when running from the shell. I suspected there is some issue with the standard output of the processes run by the cron, because in such case there is no meaningful notion of standard output.

As it turns out, programs executed by cron have no terminal attached to their standard output. According to this Stack Exchange post the standard output is sent to the system’s mail system and thus delivered to a user this way. One can easily verify this by issuing tty command in the cron and redirecting the output to a file. Something similar to this is not a terminal (message translated directly from my system with Polish locale) should be observed.

The further explanation goes as follows: if there is no terminal attached to the process, the Python interpreter cannot detect the encoding of the terminal (it has nothing to do with the system’s environmental variables describing locale. They are all global and are part of the process’ environment, but they do not affect the non-terminal device being attached to standard output). You can verify this by running a Python script that tries to output terminal’s encoding: print sys.stdout.encoding. The None can be observed. So, the interpreter falls back to Ascii encoding and crashes when printing Unicode characters.

The solution in this case was to enforce the interpreter to use Unicode encoder for standard output.

UTF8Writer = codecs.getwriter('utf8')
sys.stdout = UTF8Writer(sys.stdout)

The output is discarded at all, but these lines prevent the interpreter from using default Ascii encoder which is not appropriate for printing Unicode string.

Less known feature of C# 5.0 — modified closure behaviour

If you were asked to mention new features of C# 5.0, then you would probably say, first of all, async / await. However, on MSDN there is list of changes that could hardly be considered as well-known, even after almost 1 year after .NET 4.5 RTM was published. In this post I briefly explain one of them, that in my opinion is worth remembering.

As a C# developer, you are hopefully aware of the outer variable trap issue. Yet, in the version 5.0 of the language, the behaviour of a closure has been slightly altered. Let’s take a look at first (regarding comment “switches”) half of the following code:

 
class Program
{
  static void Main(string[] args)
  {
    //* 
    List<Action> lambdas = new List<Action>();
    foreach (var i in new int[] { 0, 1 })
    {
      lambdas.Add(() => { Console.WriteLine(i); });
    }

    lambdas[0]();
    lambdas[1]();

    /*/

    List<Action> lambdas = new List<Action>();
    for (int i = 0; i <= 1; i++)
    {
      lambdas.Add(() => { Console.WriteLine(i); });
    }

    lambdas[0]();
    lambdas[1]();    

  //*/
  }
}

Now let’s try to compile it using version 3.5 and 4.5 of the compiler. This assumes default installations, the file is named Program.cs and, of course, as 4.5 version of run-time is in-place update, it resides in the directory named after 4.0.

  1. c:\Windows\Microsoft.NET\Framework\v3.5\csc.exe Program.cs && Program
  2. c:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe Program.cs && Program

The former example results in 1 1 printed into the console and the latter results in 0 1 printed. The 1 1 result is caused by typical outer variable trap, where the lambdas are kind of bound to the captured variable itself (which in the end has a value of 1), but not to its value at the time of creation of the lambda. The breaking change introduced in version 5.0 of the language brings the behaviour to what actually might have been expected — capture the value indicated by the sequence of the code being executed. However, this works only inside foreach loop.

By switching the comments (deleting the first slash) you can prove standard for loop behaves exactly the same in both versions of compiler and results in printing 2 2 indicating outer variable trap.

Interface type parameter covariance and contravariance in C#

  • I would like this blog post to serve as a quick reference that recalls the basic concept of covariant and contravariant type parameters of generic interfaces in the C# language.
  • I tried to keep the example as simple as possible. Included comments explain the key points. No long stories and no dissertations.
  • The code does nothing, but compiles on C# 4.0 or newer compiler.
  • Try deleting the first slash character in the first line to kind of switch between the snippets (BTW this is cool trick 🙂 ).
//*
  // T is covariant
  // Implicit conversion from interface instance I<B> which has a method with RETURN type B
  // that is MORE derived than specified in target interface I<A>
  public interface I<out T> { T foo(); }
  public class IImp<T> : I<T> { public T foo() { return default(T); } }
  public class A { }
  public class B : A { }

  class Program
  {
    static void Main(string[] args)
    {
      I<A> ia = new IImp<B>();
    }
  }
/*/
   // T is contravariant
   // Implicit conversion from interface instance I<A> which has a method with ARGUMENT type A
   // that is LESS derived than specified in target interface I<B>
   public interface I<in T> { void foo(T t); }
   public class IImp<T> : I<T> { public void foo(T t) { } }
   public class A { }
   public class B : A { }

   class Program
   {
     static void Main(string[] args)
     {
       I<B> ia = new IImp<A>();
     }
   }
//*/

Quick-tip: Using newest Entity Framework assembly in ASP.NET MVC 4

For me it has been kind of unexpected behavior. When I update NuGet package, I get newest Entity Framework binaries. Today it is version 5.0. However, default MVC template targets .NET version 4.0. Newest version of Entity Framework for .NET 4.0 is 4.4. The NuGet package contains both assemblies, but the project will use 4.4 because the project targets .NET 4.0 by default. Furthermore, simply changing target runtime version in project properties is not enough. What finally has worked for me was manually editing .csproj file. I located assembly reference in XML and changed path in HintPath tag from \lib\net40\EntityFramework.dll to \lib\net45\EntityFramework.dll. The conclusion is to pay close attention to what particular version of assembly is actually being referenced and not relying only on NuGet versioning.