Blog

For the English part of the blog, see Content AND Presentation.

2019-06-15 Debugging Node.js programs in a Vagrant virtual machine

One of the very nice things in a programmer’s toolbox is a debugger. Coming from Emacs, I am accustommed to Edebug, which allows to step through the code, install breakpoints (conditional ones as well as unconditional ones), watch variables etc.

Programming in JavaScript is (or at least should be) no different. Indeed, both Firefox and Chromium have a debugger in their DevTools (although Chromium’s one seems a tad more confusing). This is all good when I’m debugging front-end code, but I often work on some backend code in Node.js.

Fortunately, it can be debugged, too. There is the --inspect argument to node which allows for using Chromium to debug Node.js code. Here is how you can use it.

Let us first write a simple Node.js script:

console.log('Hello');
console.log('world!');

and save it as, say, /tmp/hello-world.js. Now, instead of saying node /tmp/hello-world.js, let’s say node --inspect /tmp/hello-world.js.

Well, (almost) nothing interesting happens, apart from two lines displayed by Node.js debugger. This is because there are no breakpoints in our code. We could insert a debugger directive in this code, but nothing would happen then. (I suspect that was because I didn’t manage to open the Chromium debugger fast enough and the code reached the debugger directive before connecting to Chromium. In such a case, it is ignored. At least, a short experiment with a suitable sleep confirms this conjecture.) However, we can also use the --inspect-brk argument, which sets a breakpoint right at the beginning of our script.

How do we now attach the Chromium debugger to our script? Let us run node --inspect-brk /tmp/hello-world.js and then switch to Chromium. After pointing it to the chrome://inspect url, we click the Configure... button and add a row of the form localhost:9229. Bingo! Two links appear now: Open dedicated DevTools for Node and inspect, right below the filename of our script. I have honestly no idea whether there is any difference in clicking either of the two, but even if not, I’d prefer the second one, since at allows to choose the script in an unlikely event of debugging two scripts at once.

Now that we click inspect, a DevTools window should open and show our code. Congratulations! We can now step through the code, view (and even change!) variable values etc.

Well, this is all good and fun, but in reality, I faced one more problem. Most of the Node.js code I have is executed in a virtual machine (we use Vagrant and VirtualBox). I thought that I could just edit Vagrantfile to enable port forwarding, so that guest’s port 9229 is forwarded to e.g. 9221 on the host machine. Unfortunately, for some reason I could not make it work. Luckily, there is another way.

As the friendly manual suggests, we can use ssh’s -L option, which is another way of setting up port forwarding. We can now say e.g. vagrant ssh -- -L 9221:localhost:9229 (and add localhost:9221 to the Chromium inspect configuration; of course, nothing stops us from using 9229 on both the host and guest machines, too). Now we can just run node --inspect-brk on the VM, and Chromium inspector just works. That’s it!

There is one more thing that can be said here: we can use some other client instead of Chromium. There are a few such clients. One is built into Node.js (just say node inspect hello-world.js and see what happens – this looks a bit crude, but hey, it’s terminal based!). Of course, there is another one (Indium), which I hope to experiment with, since it is Emacs-based.

CategoryEnglish, CategoryBlog, CategoryJavaScript

Comments on this page

2019-06-09 Defining custom TikZ fill patterns

Some time ago I had a need to define my own filling pattern in TikZ. It turned out to be quite simple, although I had to learn a few things. While the manual (as usual) does a pretty good job at teaching that, I felt that the explanation was a bit too short in one place, and hence this blog post.

First of all, I will deal with “form-only” patterns here. I guess “inherently colored patterns” are pretty similar.

The entry point here is the \pgfdeclarepatternformonly macro. It accepts five mandatory arguments, possibly preceded by an optional one. Let’s forget about the optional parameter for a moment and talk about the mandatory ones.

The first one is easy – the name of the pattern. I’m not sure whether it’s documented anywhere (probably yes), but it seems pretty obvious that using a backslash in the name is prohibited, and using other characters with atypical catcodes (like a tilde, a caret etc.) is risky business – I tend to stay with letters, digits and spaces.

The second and third parameters are the “bottom left” and “top right” points. The define what the manual calls the “bounding box” of the pattern “tile”. This has an effect of defining the part of the Cartesian plane where it makes sense to put the drawings on, since all you draw in the last parameter will be clipped to that rectangle. The fourth parameter is the “size” of the tile, which is one point, whose coordinates are the width and height of the tile. The last parameter (as mentioned) is the actual code that makes the drawing – we’ll get to this in a minute.

Now there is a legitimate question of why we specify the tile size twice. The manual explains that, though at first I wasn’t sure if I understood the explanation: the bounding box is related to the actual size of what is visible (as mentioned above, it is used for clipping), and the tile size is related to how dense on the plane the drawing will be put.

This means that while it is possible to specify the bounding box to be smaller than the tile size, it seems there is no point in doing so. (I don’t know of any performance penalty, but I doubt one exists.) However, specifying a bounding box smaller than the tile size makes perfect sense – an identical visual effect can be achieved without it, but it might be both more difficult to code and slower to draw.

Before we look at some examples, let me mention that the “code” (the last parameter) should be low-level PGF code which actually makes the drawing. (Low-level here means “using the so-called «basic layer» of PGF, described towards the end of the TikZ manual.) I will not spend time here for that – this part is well documented (and pretty boring).

So, let us now look as some examples. Assume that we want to fill the plane with small circles. Here is the first version, where the bounding box is a square equal in size to the tile and the circles’ diameters are equal to the tile’s side.

\documentclass[tikz]{standalone}

\usetikzlibrary{patterns}
\pgfdeclarepatternformonly
  {circles1}                     % name
  {\pgfqpoint{-6pt}{-6pt}}      % bottom left
  {\pgfqpoint{6pt}{6pt}}        % top right
  {\pgfqpoint{12pt}{12pt}}      % tile size
  {                             % code
    \pgfsetlinewidth{2pt}
    \pgfpathcircle{\pgfpointorigin}{6pt}
    \pgfusepathqstroke
  }

\begin{document}
\begin{tikzpicture}
  \fill[pattern=circles1] (0,0) rectangle (8,2);
\end{tikzpicture}
\end{document}

tikz-patterns-1.png Here, nothing unexpected happens. Let us now shake things a bit. What would happen if we increased the tile size? The answer is easy: we would be able to actually observe the clipping in action.

\pgfdeclarepatternformonly
  {circles2}                    % name
  {\pgfqpoint{-6pt}{-6pt}}      % bottom left
  {\pgfqpoint{6pt}{6pt}}        % top right
  {\pgfqpoint{16pt}{16pt}}      % tile size
  {                             % code
    \pgfsetlinewidth{2pt}
    \pgfpathcircle{\pgfpointorigin}{6pt}
    \pgfusepathqstroke
  }

tikz-patterns-2.png

If we increased the circles’ radii instead, we would see the circles clipped even more.

\pgfdeclarepatternformonly
  {circles3}                    % name
  {\pgfqpoint{-6pt}{-6pt}}      % bottom left
  {\pgfqpoint{6pt}{6pt}}        % top right
  {\pgfqpoint{12pt}{12pt}}      % tile size
  {                             % code
    \pgfsetlinewidth{2pt}
    \pgfpathcircle{\pgfpointorigin}{7pt}
    \pgfusepathqstroke
  }

tikz-patterns-3.png

To obtain properly overlapping circles, we obviously need to increase the bounding box, too.

\usetikzlibrary{patterns}
\pgfdeclarepatternformonly
  {circles4}                    % name
  {\pgfqpoint{-7pt}{-7pt}}      % bottom left
  {\pgfqpoint{7pt}{7pt}}        % top right
  {\pgfqpoint{12pt}{12pt}}      % tile size
  {                             % code
    \pgfsetlinewidth{2pt}
    \pgfpathcircle{\pgfpointorigin}{6pt}
    \pgfusepathqstroke
  }

tikz-patterns-4.png

Of course, we could play with the options more, but I hope that the interplay between the bounding box and tile size is obvious now.

Notice that this is not the whole story: there is the optional argument (“variables”), which allows for using variables. This, however, is documented more extensively, so there is no need to cover it here – just consult the manual to see a nice example (in fact, very similar to what we did here).

CategoryEnglish, CategoryBlog, CategoryTeX

Comments on this page

2019-06-03 Undoing without redoing

Emacs has a somewhat atypical undo feature – if you undo some changes (possibly more than one), and then break the sequence of undo commands (for example, by moving the point), any subsequent undo will, well, undo the previous undo – in other words, Emacs’ undo doubles as redo.

If you find this behavior confusing, you are not alone. The linked thread has two important tips, though. First of all, you can use the built-in undo-only command, which works exactly as the plain undo except that it does not exhibit the “redo” behavior.

A more sophisticated solution, also mentioned in the thread, is the undo-tree package. Personally, I learned to use the default Emacs undo system, and especially its behavior when the region is active. (Search the manual for “selective undo” to learn more.)

Probably the most interesting takeaway from that thread was that a new user of Emacs found the undo behavior confusing, but later – after some time and getting accustomed to it – did not really want to change it after all. Maybe that means that the Emacs way is better, maybe not – in either case you can make Emacs do what you want.

CategoryEnglish, CategoryBlog, CategoryEmacs

Comments on this page

More...