Thursday, March 12, 2015

Console editor with Notepad behavior

When I started using Linux (it was Ubuntu in 2007), I wanted a console text editor which would support keyboard shortcuts used in Windows Notepad:

- Ctrl + Left/Right -- go to the beginning/end of the previous/next word
- Ctrl + Home/End -- go to the beginning/end of the file
- Shift + Left/Right -- select previous/next character
- Control + Shift + Left/Right -- select previous/next word
- Control + Shift + Home/End -- select line to the beginning/end
- Control + C/V/X/Z -- copy/paste/cut selected text, undo last operation

Nano, which is present in Ubuntu out of the box, is quite simple, but doesn't support almost all of the shorcuts.

Vim -- I didn't like it immediately -- I even didn't know to close it.

Emacs -- I could not exit it either, but I liked it more.

In the end I stopped looking and used what I have -- Vim/Emacs/Nano.

But today I found out that Emacs starting with version 22.1.1 has Cua mode.
The command M-x cua-mode sets up key bindings that are compatible with the Common User Access (CUA) system used in many other applications.
Add this to `~/.emacs`:

(cua-mode t)
(setq cua-auto-tabify-rectangles nil) ;; Don't tabify after rectangle commands
(transient-mark-mode 1) ;; No region when it is not highlighted
(setq cua-keep-region-after-copy t) ;; Standard Windows behaviour

and it works!

Be aware that Emacs has its own clipboard, and Ctrl+V will not paste system clipboard contents.

Sunday, March 8, 2015

Shell script argument with a default value

So, I made I shell script which makes some backup copies. I want it to accept one argument which is the directory where to store the backups. And if it was not provided, it should have some default value.

This works:
if [ -z "$1" ]; then
echo "${BACKUP_DIR}"

But it's too verbose. Of course you could write it in one line, but here is a nicer version:
[ -z "$1" ] && BACKUP_DIR="/home/ubuntu/backups" || BACKUP_DIR="$1"

But the variable name is repeated twice. We can do better:

BACKUP_DIR=$([ -z "$1" ] && echo "/home/ubuntu/backups" || echo "$1")

But I think this is the clear winner:


If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.

Friday, January 23, 2015

URLs vs URIs

Whenever I needed to work with a URL in my code I wasn't sure how to name the variable: `url` or `uri`? What term to use in documentation: URL or URI?

Some projects use term `URI` ( `Connection URI` in Flask,  `redirect_uri` in Facebook API). Other projects use term `URL` (like SqlAlchemy or `redis.from_url`).

I've been thinking about this occasionally in the last several years. Today, after reading again the Wikipedia article about URI I reached a conlusion.

A URN is a URI that identifies a resource by name in a particular namespace. A URN can be used to talk about a resource without implying its location or how to access it.
The International Standard Book Number (ISBN) system for uniquely identifying books provides a typical example of the use of URNs. ISBN 0-486-27557-4 cites unambiguously a specific edition of Shakespeare's play Romeo and Juliet. The URN for that edition would be urn:isbn:0-486-27557-4. To gain access to this object and read the book, its location is needed, for which a URL would have to be specified.

A URL is a URI that, in addition to identifying a web resource, specifies the means of acting upon or obtaining the representation, specifying both its primary access mechanism and network location. For example, the URL refers to a resource identified as /wiki/Main_Page whose representation, in the form of HTML and related code, is obtainable via HyperText Transfer Protocol (http) from a network host whose domain name is

In other words: the URN defines an item's identity, while the URL provides a method for finding it.

Or in my words, URN is like an identifier of a resource, and URL is identifier of one of its locations (but not resources global identity).

So, every URL is a URI, but not every URI is a URL.

So, if we talk about a database whose location we want to put into settings, we should use term URL, because it's a location (`postgresql://scott:tiger@localhost/mydatabase`)! Using an URN (something like `urn:database:6e8bc430-9c3a-11d9-9669-0800200c9a66`) would not work in these cases. So if we can't use URNs, we should not use term URI which includes URN.

Thursday, January 1, 2015

Websockets chat in Python

I've made a simple Websockets server in Python using Flask + gevent-websocket.

The idea was taken from

It uses Redis Pub/Sub subsystem to ensure that all connected clients receive the messages, even if there are several Gunicorn workers.

See the code here:

Feel free to comment and improve.

Saturday, December 20, 2014

Do people lose interest in programming as they age?

Some younger programmers expect that older programmers are slower, make more mistakes, and would rather be doing something else such as managing programmers. Are they right to think so?

Rod Johnson 
Written 14 Dec.

In my experience, ability and attitude is what differentiates programmers, not age. The IT industry suffers from rampant agism, which deserves to be called out. Somehow agism is considered more acceptable than sexism, when it's equally wrong.

Regarding whether people appear to lose interest in programming, I think it often depends on whether they had real interest in the first place. A lot of people become programmers with little passion, and many of them realize that they also lack real aptitude. Such people will jump at a chance to move into management: Where they will often also fail, but may have a better chance of getting away with it.

However, it is true that many passionate, competent programmers (like myself) move into business or management jobs as their career progresses. I can think of several reasons for this, most of them nothing to do with advancing age:

  • Necessity. Often someone emerges as a natural leader in a specific project, and it's the best thing for all concerned for that person to take on more and more management responsibility.
  • Opportunity. For example, when a programmer becomes an entrepreneur.
  • Concern about encountering age discrimination. While great programmers will always be employed, regardless of their age or the state of the economy, average and even good programmers can start to be frozen out as they get older, and they change track to avoid the problem.
  • Unwelcoming environment for older programmers. I have mid 40s friends who are starting to find working as Google engineers uncomfortable, despite being good at their jobs.
  • Desire for career variety. I personally could not imagine doing the same thing--even something awesome like programming--for my entire career, any more than I could imagine living my entire life in the same country or spending my entire career at the one company.
  • Desire to do a more people-centric job, at least part of the time. I loved (and still love) writing code, but also get a huge buzz out of working closely with people and talking about human, rather than technical, issues.
  • Discovery of new areas of passion. In my case, I discovered, initially to my great surprise, that I found many business problems intensely interesting, and enjoyed management.

Having said that, I don't think a passionate programmer ever loses the buzz programming can provide. It's addictive. It may just become a hobby rather than a day job.


Saturday, November 15, 2014

Prepopulate a `user` field in a Django admin form

It took me a while to find the solution, which I am posting here:
class ArticleAdmin(admin.ModelAdmin):

    form = ArticleAdminForm

    def get_changeform_initial_data(self, request):
        initial = super().get_changeform_initial_data(request)
        initial['submitted_by'] = request.user
        return initial

Tuesday, November 11, 2014

Implementing a ReDiS COUNT command in Lua

Inside of a Blog: Implementing a ReDiS COUNT command in Lua: I have recently been implementing a master/slave redis cache for our enterprise application and at certain points during the development/test phases, have found it useful to be able to query redis for the # of keys that have been inserted that match a certain regex...

In short:

eval "return #redis.pcall('keys', '*')" 0