Monday, December 30, 2013

Zsh History Search

Compared to Fish, currently I like Zsh a little bit more. But one of the unforgettable feature of Fish is its auto-suggestion based on history.
It made command line input so fluent.

Zsh has a feature similar to that called predict. You could configure by placing the following codes in your ~/zshrc.
You could press <Ctrl-Z> to toggle predict on and off.

autoload predict-on
predict-toggle() {
  ((predict_on=1-predict_on)) && predict-on || predict-off
}
zle -N predict-toggle
bindkey '^P'   predict-toggle
zstyle ':predict' toggle true
zstyle ':predict' verbose true

But compared to Fish’s auto-suggestion, I feel that the predict feature is less useful.
The difference show up when you simply type ls<Enter>.

  • In Fish, only ls will be executed.
  • In Zsh, if predict was turned on, ls -la will be executed, which is sometimes not what we want.

So for a more convenient way of accessing command line history, I prefer Zsh’s vi mode and history-search-backward.
You could press <Ctrl-J> and <Ctrl-K> to search history forward and backward.

# vi mode
setopt vi

# bind k and j for history search in vi mode
bindkey -M viins '^k' history-search-backward
bindkey -M viins '^j' history-search-forward
bindkey -M vicmd '^k' history-search-backward
bindkey -M vicmd '^j' history-search-forward

YCM with Clang on Windows

YCM, short for YouCompleteMe, is a fast, as-you-type, fuzzy-search code completion engine for Vim. If built with Clang (v3.2+) support, then it can provide
petty code completion for C/C++ code. On linux, we can get or build Clang easily, but on Windows, it not only hard to build, but also not works well.

Listed below are the steps to compile clang on Windows using MinGW64 and make it work with YCM. Pleas note that the Clang built using this methods can only work as parser, instead of a compiler.
That is to say, you can only use it with YCM to provide code completion, and you won’t be able to use it to compile your code. The reason is that the executable file generated by the Clang we build will crash.

1. Download and install MinGW64

Mingw-w64 is a project that provides support to both 64 bit (x64) and 32 bit (x86) GCC on windows.
You could download the MinGW-w64 package using the link below. You could refer to the reason why we use this particular version on Qt.org.

2. Download and install MSYS.

MSYS is a collection of GNU utilities on Windows.

3. Install SVN

Please download and install SVN. Please make sure svn.exe is on on PATH

4. Get LLVM and Clang code

In a MSYS terminal, execute the following commands to get the Clang’s source code. In my case, it is r192871.

cd ~
svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm

cd ~/llvm/tools
svn co http://llvm.org/svn/llvm-project/cfe/trunk clang

cd ~/llvm/projects
svn co http://llvm.org/svn/llvm-project/compiler-rt/trunk compiler-rt

5. Modify Clang’s code to let Clang know about our include path.

vi ~/llvm/tools/clang/lib/Frontend/InitHeaderSearch.cpp

Find the following method.

void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple, const HeaderSearchOptions &HSOpts) {

Within the method, find the following line.

case llvm::Triple::MinGW32:

Add the following lines to right below that position.

// mingw-build C++ include paths
AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "i686-w64-mingw32", "4.8.0");

6. Build LLVM & Clang

In the MSYS terminal, execute the following commands to build Clang.

cd ~
mkdir build
cd build
export CC=gcc
export CXX=g++
../llvm/configure --disable-docs --enable-optimized --disable-assertions --enable-targets=x86,x86_64 --prefix=/mingw
make
make install

7. Install Vim and YCM.

8. Build YCM core

# cd <your YCM folder>
mkdir build && cd build
cmake -G "Unix Makefiles" -DPATH_TO_LLVM_ROOT=/mingw -DTEMP=/mingw/bin/clang.dll . ../cpp
make ycm_core
cp ycm/ycm_core.pyd ../python/ycm_core.dll

That’s it. Enjoy YCM on Windows.

For more information, please refer to the following links.

Setup Pip and Virtualenv

In case we need to run python programs that depends on different versions of same libs, we need to create isolated python environment to avoid those libs interfere with each other. There are two tools can help us achieve that, pip and virtualenv.

1. Install pip

Pip is a package manager used to install and manage python packages. On ubuntu (13.04), you could install it via the following command. You could also download it from here.

sudo apt-get install pip

Note: Depending on your python versions, you may want to install pip or pip-3.x package.

2. Install virtualenv

Virtualenv is the tool to create isolated python environments. On ubuntu you could use apt sources to install virtualenv, or you could always use pip to install it.

sudo pip install virtualenv

3. Create a virtual environment

Once you have the tools installed, you could create a virtual environment using the following command.

virtualenv myenv

4. Use a virtual environment

To use the virtualenv, you could activate it by executing the following command. Basically speaking, it prepend the virtualenv/bin to your $PATH environment variable.

cd myenv
. bin/activate

5. Leave a virtual environment

The following command will revert the changes made by the activate script.

deactivate

Setup Pelican

[Pelican] is a static site generator, written in Python. It allows you write your content in Markdown and reStructuredText. It uses
Here are the steps to setup a hello world [Pelican].

1. Install pip and virtualenv

It is highly recommended to use a virtualenv to create isolated python environment and use pip to manage your packages.
You could refer to my post [Setup Pip and Virtualenv] for instructions to install them.

2. Create a virtual environment

Once you installed virtualenv, you could activate your virtual environment by executing the following command.

virtualenv pelican
cd pelican
. bin/activate

About the last line, if you are using Fish shell, you may need to use . bin/activate.fish instead.

3. Install required packages

pip install pelican markdown

4. Create pelican configuration file

There is a quick start program pelican-quickstart than can help you create a pelican configuration file quickly.
The program will ask you several questions to gather the information needed.

> Where do you want to create your new web site? [.] 
> What will be the title of this web site? Hello World Blog
> Who will be the author of this web site? Your Name
> What will be the default language of this web site? [en] 
> Do you want to specify a URL prefix? e.g., http://example.com   (Y/n) Y
> What is your URL prefix? (see above example; no trailing slash) http://hello-world-blog.com
> Do you want to enable article pagination? (Y/n) Y
> How many articles per page do you want? [10] 8
> Do you want to generate a Fabfile/Makefile to automate generation and publishing? (Y/n) Y
> Do you want an auto-reload & simpleHTTP script to assist with theme and site development? (Y/n) Y
> Do you want to upload your website using FTP? (y/N)
> Do you want to upload your website using SSH? (y/N)
> Do you want to upload your website using Dropbox? (y/N)
> Do you want to upload your website using S3? (y/N)
> Do you want to upload your website using Rackspace Cloud Files? (y/N)

5. Draft the first post

Create a markdown file in content folder.

mkdir content
vim content/the-first-post.md

And paste the following content into it.

Title: Hello World
Date: 2013-10-25
Category: Misc

# Hello World

6. Generate HTML files

After the following command succeeded, HTML files will be generated in output folder.

pelican content -s pelicanconf.py -o output

7. Preview the blog

You could start a local HTTP server by running the following command,
and then you can preview your site at http://localhost:8000

cd output && python -m SimpleHTTPServer

Make Python 3.x Default Python on Ubuntu

If you installed both python version 2.x and 3.x on system, you could add the following line to your ~/.bashrc or ~/.zshrc to make python 3.x the default python.

alias python='python3'

If you want to make pip-3.x and virtualenv-3.x your default ones, you may also add the following lines.

alias pip='pip-3.3'
alias virtualenv='virtualenv-3.3'

Floating Point Binary Representation in C++

Interested in how a float point number is stored in memory? The following C++ code can print it out.

#include <iostream>
#include <bitset>

using namespace std;

int main() {
    float f = 3.14159;
    bitset<32> bs(*(int*)&f);
    cout << bs << endl;
}

The output is 01000000010010010000111111010000.

Apache Thrift

Apache Thrift is a framework for scalable cross-language services development. Compared to SOAP-based and JSON-based web services, Thrift uses its own interface definition language and binary format in communication.

Here are the steps to setup thrift and use it to build a hello world web service.

1. Get Thrift source code.

git clone https://git-wip-us.apache.org/repos/asf/thrift.git thrift
cd thrift

2. Install required tools and libraries.

sudo apt-get install libboost-dev libboost-test-dev libboost-program-options-dev libevent-dev automake libtool flex bison pkg-config g++ libssl-dev

3. Build and install Thrift

./bootstrap.sh
./configure
make
make install

4. Define a simple service interface

# helloworld.thrift
service Foo {
    string bar();
}

5. Generate boilerplate codes

thrift --gen cpp helloworld.thrift
thrift --gen py helloworld.thrift

6. Implement the server in C++.

In gen-cpp folder, edit the file Foo_server.skeleton.cpp, which is an auto-generated skeleton file for server implementation.

class FooHandler : virtual public FooIf {
 public:
  void bar(std::string& _return) {
      _return = "Hello World";
  }
};

In gen-cpp folder, create a CMakeLists.txt file with the following content.

cmake_minimum_required (VERSION 2.6)
project (server)
link_libraries(libthrift.so)
aux_source_directory(. sources)
add_executable(server ${sources})

Then run the following commands.

cmake. && make

7. Implement the client in Python.

In gen-py folder, create a client.py with the following content.

import sys
from thrift.transport import TTransport
from thrift.transport import TSocket
from thrift.protocol import TBinaryProtocol
from helloworld import Foo
from helloworld.ttypes import *

socket = TSocket.TSocket('localhost', 9090)
transport = TTransport.TBufferedTransport(socket)
protocol = TBinaryProtocol.TBinaryProtocol(transport)
client = Foo.Client(protocol)
transport.open()
print(client.bar())
transport.close()

9. Start server.

cd gen-cpp
server &

10. Start client.

cd gen-py
python client.py

And the text Hello World should be printed out.

Keep Both Python 2 and Python 3 on Windows

Here is notes to keep both Python 2 and Python 3 working on Windows.

New in Python 3.3

Start from Python 3.3, there is a py.exe installed to %SystemRoot% directory, which is helpful when multiple versions of Python installed.
  • py -2 and py starts Python 2.x
  • py -3 starts Python 3.x

Use shebang in Python scripts

In favor of py.exe, shebang in Python scripts can be recognized on Windows.
  • #! python 3 for Python 3.x
  • #! python 2 for Python 2.x

Installation order matters

If you install python3 first and then Python 2, the setup program of Python 2 will overwrite the .py file association, such that a Python 3 script with shebang #!python 3 will be executed by Python 2. So the better order is install Python 2 first and then Python 3.

Don’t need to add python to PATH

If both Python 2 and Python 3 executables are on PATH, then there will be confusion. Instead of add Python to PATH and call python your-script.py, the following command also work your-script.py.