thefourtheye's weblog

opinions are my own; try code/suggestions at your own risk

Emacs - Cheat Sheet

| Comments

After having been in the vim camp in the vim vs Emacs editor war for eight years, I decided to peek into the enemy’s camp. The IDE users might look down upon the editor users, but I still enjoy using my keyboard to do all the coding work. That is the reason why I chose to learn Emacs over an IDE.

When I started with Emacs, it was kind of scary. Editing text is straight forward, as in, it didn’t require me to change the mode like in Vim. But the control key sequences are way too much to remember compared to Vim. So I decided to understand the keys which are commonly used to move around the text in the screen, with the help of Emacs Tutorial (Ctrl+h t).

This cheat sheet has a few more key combinations which are used to do common operations on Emacs.

Note: From now on, the Ctrl key will be represented as C and the Alt key (also called as Meta key) will be represented as M. For example, if the actual command is to press both Ctrl and h keys to invoke the help, then it would be written as C-h.

Common Operations

Key Combinations Functionality
C-x C-c Quit Emacs
C-h t Open built-in Emacs Tutorial file
C-x C-f Open a File
C-x k Close the currently opened file on screen
C-x C-s Save the currently opened file
C-x s Save all the open files
C-g Discard the current command

Split Window Operations

Key Combinations Functionality
C-x 2 Split the view horizontally
C-x 3 Split the view vertically
C-x o (English letter “o”) Switch to next split window
C-x 0 (Number Zero) Kill the current window
C-x 1 Kill all other split windows except current window
C-x C-b List all open files in a new split window
C-x b Bring any of the open files to the front, by name

Cursor Movement

Key Combinations Functionality
C-b Move one character backward
M-b Move one word backward
C-f Move one character forward
M-f Move one word forward
C-v Scroll one page full of information forward
M-v Scroll one page full of information backward
C-a Beginning of current line
M-a Beginning of current sentence
C-e Ending of current line
M-e Ending of current sentence
M-> End of file
M-< Beginning of file
C-n Next line
C-p Previous line
C-l Move the current line to bottom, middle, and start of screen

Edit Operations

Key Combinations Functionality
C-x u C-/ Undo last operation
C-k Delete till the end of the current line from current position
M-k Delete till the end of the current sentence from current position
C-d Delete the next character
M-d Delete the next word
C-<Del> Delete the previous character
M-<Del> Delete the previous word

Copy and Paste

Key Combinations Functionality
C-<Space> Set mark to select text. Now with movement keys select the text
C-x h Select the whole buffer
C-w Cut the selected text
M-w Copy the selected text
C-y Yank (paste) the selected text

JavaScript Lookbehind RegEx Alternative

| Comments

Recently one of my colleagues came to me with a problem. He had a string which looked like JSON but not a valid JSON string. For example,

[{\"name\":\"Kilua\"\\,\"age\":35}],{\"city\":\"SJC\"},\"US\"

and they wanted to split the string at all the commas, except when they are preceded by a backslash. That means, they wanted

[ '[{"name":"Kilua"\\,"age":35}]', '{"city":"SJC"},"US"' ]

as output. If the requirement was to split the string at commas followed by a certain string, then it would have been pretty straight forward. For example, if the string is a,1,b,2,c,3 and if they wanted to split the string at all commas except when they are not followed by numbers, then the solution would have been very simple, with negative lookahead, like this

console.log('a,1,b,2,c,3'.split(/,(?!\d)/));
// [ 'a,1', 'b,2', 'c,3' ]

Since JavaScript doesn’t have lookbehinds, we don’t have a straight forward solution to this problem. When I searched Stackoverflow, I found this solution

WTK's answer in Stackoverflowlink
'a\\,bcde,fgh,ijk\\,lmno,pqrst\\,uv'.replace(/([^\\]),/g, '$1\u000B').split('\u000B')

This solves the exact same problem which my colleague was facing. It compensates the absence of lookbehinds by breaking down the problem in two steps.

  1. Replace all the commas matching the condition with a marker string which does not appear anywhere in the string. (\u000B in this case)
  2. Then split the original string with the marker string.

JS Quirks: Stringified Numbers

| Comments

When I was working on Node.js PR 9492, this comment

This should probably test for a wider range of values. test/parallel/test-net-internal.js has some good examples.

made me look at that file. As I was going through the test, few of the bad values were interesting. I normally test with stringified positive decimal numbers and negative decimal numbers. But I saw stringified negative octal, binary, and hexa decimal numbers.

const bad = [-1, 'a', {}, [], false, true, 0xFFFF + 1, Infinity,
             -Infinity, NaN, undefined, null, '', ' ', 1.1, '0x',
             '-0x1', '-0o1', '-0b1', '0o', '0b'];

I got curious as I have never used them before, I just wanted to see their corresponding negative values. So I wrote a program like this

[-0x1, '-0x1', -0o1, '-0o1', -0b1, '-0b1'].forEach(item => console.log(item, +item));

and I was expecting to see the result

-1 -1
-0x1 -1
-1 -1
-0o1 -1
-1 -1
-0b1 -1

but all I got was

-1 -1
-0x1 NaN
-1 -1
-0o1 NaN
-1 -1
-0b1 NaN

The unary - operator simply negates the magnitude of the numbers. The stringified numbers were not processed in the same way as their number counterparts. So I looked at the ECMAScript specification’s ToNumber Applied to the String Type section (which is actually responsible for converting strings to numbers).

StrNumericLiteral :::
    StrDecimalLiteral
    BinaryIntegerLiteral
    OctalIntegerLiteral
    HexIntegerLiteral
...
...
StrDecimalLiteral :::
    StrUnsignedDecimalLiteral
    + StrUnsignedDecimalLiteral
    - StrUnsignedDecimalLiteral

Only the StrDecimalLiteral production allows signed numbers. If we look at the definition of others in the Numeric Literals section,

BinaryIntegerLiteral ::
    0b BinaryDigits
    0B BinaryDigits

BinaryDigits ::
    BinaryDigit
    BinaryDigits BinaryDigit

BinaryDigit :: one of
    0 1

OctalIntegerLiteral ::
    0o OctalDigits
    0O OctalDigits

OctalDigits ::
    OctalDigit
    OctalDigits OctalDigit

OctalDigit :: one of
    0 1 2 3 4 5 6 7

HexIntegerLiteral ::
    0x HexDigits
    0X HexDigits

HexDigits ::
    HexDigit
    HexDigits HexDigit

HexDigit :: one of
    0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F

So, as per the specification, only the decimal numbers can have signs in the stringified number form. That is why the others are not considered as numbers.

DSL-2730U Router's Ipv6 Problem in Ubuntu

| Comments

Today I faced a very strange problem. I got a new Tata DOCOMO connection and I wanted to fetch upstream changes from a GitHub repository, with git fetch --all. But all I got was
fatal: unable to access 'https://github.com/<repo>': Failed to connect to github.com port 443: Network is unreachable
I thought that the internet connection has a problem. But then I was able to ping github.com and access that site in my browser, although curl still failed.
➜  io.js git:(master) ✗ curl https://github.com
curl: (7) Failed to connect to github.com port 443: Network is unreachable
At this point I became curious and tried out the verbose curl,
➜  io.js git:(master) ✗ curl -v https://github.com
* Rebuilt URL to: https://github.com/
* Hostname was NOT found in DNS cache
* Trying 192.30.252.128...
* Trying 64:ff9b::c01e:fc81...
* connect to 64:ff9b::c01e:fc81 port 443 failed: Network is unreachable
* Failed to connect to github.com port 443: Network is unreachable
* Closing connection 0
curl: (7) Failed to connect to github.com port 443: Network is unreachable
Now, it figures out both the IPv4 address and the IPv6 address but favors IPv6 over IPv4. And it looks like, either the modem or the ISP don't support IPv6 based communication. I don't know how to confirm what the actual problem is. I tried to upgrade the firmware of my DSL-2730U router, by logging into 192.168.1.1. But it kept failing, saying the the firmware image file is too big.

So, I decided to disable IPv6 in my Ubuntu machine and I followed the instructions given here and it worked perfectly. Basically, I edited /etc/sysctl.conf file to include the following lines
# disable IPv6 on this machine
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
and then executed sudo sysctl --system and sudo sysctl -p.

Sane ECMAScript 6 Generators

| Comments

This post is cross posted in Medium, here.

I recently found one interesting thing about ES6 Generators. I come from Python background and I understood generators as in Python. So, I expected the following Python code's equivalent ECMAScript 6 code also to work as well.
>>> numbers = (num for num in range(10))
>>> for num in numbers:
... if num == 3:
... break
...
>>> next(numbers)
4
You can find the online demo for this Python program, here.

But then, when I used Babel to transpile the following code and executed it
function* NumberGenerator() {
for (var i = 0; i < 10; i += 1) {
yield i;
}
}

var numbers = NumberGenerator();

for (var num of numbers) {
if (num === 3) {
break;
}
}

console.log(numbers.next());
// {"done":true}
You can find the online demo for this JavaScript program, made with Babel's REPL, here. As you see here, when I broke out of the loop, the Generator Object got closed. This was pointed out to me by Logan Smyth in Babel's Slack discussion. I was really surprised by this behavior and found the 13.7.5.13 Runtime Semantics: ForIn/OfBodyEvaluation ( lhs, stmt, iterator, lhsKind, labelSet ) section in the ECMAScript 6 Specification, which says
If LoopContinues(result, labelSet) is false, return IteratorClose(iterator, UpdateEmpty(result, V)).
I am not sure about the rationale behind that decision, but I am convinced that it would effectively limit the potential of the Generators. So I decided to fix this.

Sane Generators

To close the iterator, Iterator.prototype.return is called. (At the time of this writing, not many JavaScript Engines support this function. You can find the support for this feature by popular engines, here.) So I decided to override that and allow the actual return function to be invoked only when explicitly called with an argument.
function returnFunction(originalReturn, genObject) {
return function(arg) {
return arguments.length ? originalReturn.call(genObject, arg) : {
done: false
};
};
}

function SaneGenerator(genObject) {
var originalReturn = genObject['return'];

if (typeof originalReturn === 'function') {
Object.defineProperty(genObject, 'return', {
value: returnFunction(originalReturn, genObject)
});
}

return genObject;
}
You can see the actual and complete implementation in my GitHub repository, https://github.com/thefourtheye/sane-generator. Now, you can use the SaneGenerator like this
function* NumberGenerator() {
for (var i = 0; i < 10; i += 1) {
yield i;
}
}

var numbers = SaneGenerator(NumberGenerator());

for (var num of numbers) {
if (num === 3) {
break;
}
}

console.log(numbers.next());
// {"value":4,"done":false}
You can find the online demo for this JavaScript program, made with Babel's REPL, here.

NPM Module

This is available as an NPM module now. https://www.npmjs.com/package/sane-generator