<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Ruslan Osipov - Programming</title>
    <description>Recent posts in Programming category on Ruslan Osipov.</description>
    <link>https://rosipov.com/</link>
    <atom:link href="https://rosipov.com/blog/categories/programming.xml" rel="self" type="application/rss+xml" />
    <pubDate>Mon, 13 Apr 2026 16:21:22 +0000</pubDate>
    <lastBuildDate>Mon, 13 Apr 2026 16:21:22 +0000</lastBuildDate>
    <generator>Jekyll v4.4.1</generator>
    
      <item>
        <title>Goodbye Disqus, hello reply by email</title>
        <description>&lt;p&gt;This is a natural follow-up to last week’s “&lt;a href=&quot;/blog/i-dont-want-a-large-audience/&quot;&gt;I don’t want a large audience&lt;/a&gt;”.&lt;/p&gt;

&lt;p&gt;I’ve long been contemplating moving further away from using Disqus. I switched to Disqus &lt;a href=&quot;/blog/abandoning-wordpress-for-octopress/&quot;&gt;back in 2014&lt;/a&gt; when I abandoned my WordPress blog for Jekyll-based Octopress. Disqus seemed like a great choice- lean, customizable, ad-free, and most importantly, allowed dynamic comments for a statically generated site (&lt;a href=&quot;/blog/static-websites-rule/&quot;&gt;since this site is just a bunch of generated HTML pages&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The reason for the switch is two-part.&lt;/p&gt;

&lt;p&gt;I don’t really have the emotional bandwidth to follow along with Disqus as a company as they revisit their values, change policies, or even just grow as a business. I think I may have been grandfathered into an ad-free plan (although that’s unclear - I have network-wide ad-blocking, and I didn’t bother enough to check if there are ads in the comments). And in principle, I can’t really fault Disqus for introducing ads for unpaid comment tiers, especially without seeing their balance sheet. Maybe the free comments took up much-needed server capacity, and it could be that paid subscriptions weren’t offsetting the costs enough. Or it could be that the company just got greedy, which wouldn’t be too surprising to me either.&lt;/p&gt;

&lt;p&gt;But more importantly, I want to see what my blog would look like with less public interaction features.&lt;/p&gt;

&lt;p&gt;Outside of tutorials (which I rarely write these days), I’m not entirely sure how valuable the comments are to my readers. In fact, I think sometimes comments can be detrimental to the reader’s enjoyment. Humans are a pack animal, and subconsciously we tend to favor things favored by others. So seeing a “100 comments” heading might make you think the post is popular for a reason, while seeing “Be the first to leave a comment” would make you consider if the piece is worth reading.&lt;/p&gt;

&lt;p&gt;This is the same reason I don’t really like “likes” and other low effort ways of engaging with content. Mostly because I’d rather have said content stand on its own. Just because something is popular, doesn’t really mean it’s good and needs to become more popular. And in part because it’s hard for me to resist wanting to chase likes, and I don’t want to spend my time doing that.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/disqus-comment-export.png&quot; alt=&quot;A screenshot of the read-only comment widget on my site.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Anywho, I exported Disqus comments (which in turn already contained comments I exported from WordPress back in 2014), and I embedded those read-only comments into the existing pages. I wanted to preserve the discourse - especially on the tutorials and more widely discussed posts, and the read-only comments work great for that. Here’s a live example: &lt;a href=&quot;/blog/prius-adventures-a-year-later/#comments&quot;&gt;Prius Adventures, a year later&lt;/a&gt;. If you want to do something like this yourself, here’s the &lt;a href=&quot;https://github.com/ruslanosipov/ruslanosipov.github.io/commit/fb65351129d11c0c3a367aa86220b7004be5ef03&quot;&gt;commit in question&lt;/a&gt;, but I think this might be too niche of a topic to warrant a step-by-step guide.&lt;/p&gt;

&lt;p&gt;I replaced the comment functionality with a &lt;a href=&quot;mailto:ruslan@rosipov.com?subject=Re: Goodbye Disqus, hello reply by email&quot; class=&quot;button&quot;&gt;✍️ Reply by email&lt;/a&gt; button which you can find at the bottom of this post. Yeah, that button simply opens your email client and pre-fills my address and the email title. That’s a private email, that only I will read, that I won’t post publicly, and others won’t see. But we might have a great conversation, which is better. Why don’t you give it a shot, and tell me if this message resonates with you?&lt;/p&gt;

&lt;p&gt;I’m not severing my site from the rest of the Internet here, no. Ever since I learned about &lt;a href=&quot;https://indieweb.org/Webmention&quot;&gt;Webmentions&lt;/a&gt;, I eventually want to add Webmention support to my site at some point. But I might only filter it down to Webmentions from long-form posts on other sites, rather than comments or likes. It’s definitely a no on likes for me. Follow along and see what I’ll do.&lt;/p&gt;

&lt;p&gt;P.S: Late addition right before hitting the publish button. I’ve just stumbled upon “&lt;a href=&quot;https://kami.bearblog.dev/why-comment-sections-suck-rei-want-to-comment-on-your-blog-post/&quot;&gt;Why Comment Sections suck - re:I want to comment on your blog post&lt;/a&gt;” from &lt;a href=&quot;https://kami.bearblog.dev/&quot;&gt;Kami’s Corner&lt;/a&gt; (thank you, &lt;a href=&quot;https://winther.sysctl.dk/postroll/&quot;&gt;winther blog postroll&lt;/a&gt; for aiding my blog discovery efforts). There’s a nugget inside that summarizes my core desire more eloquently:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;When you want to make a response you have to either email the person or write a response post. That small barrier to entry cuts out most idiots. Because you have to actually care about what you have to say to sit down and write an email or to make an entire response post. You have to put in some effort.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I’m excited to see what the future of my blog will look like with the new functionality.&lt;/p&gt;
</description>
        <pubDate>Mon, 16 Jun 2025 14:00:00 +0000</pubDate>
        <link>https://rosipov.com/blog/goodbye-disqus-hello-reply-by-email/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/goodbye-disqus-hello-reply-by-email/</guid>
        
        
        <category>Writing</category>
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>Category-specific RSS feeds in Jekyll</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://thoughts.uncountable.uk/&quot;&gt;Chris Shaw&lt;/a&gt; asked me if I had category-specific RSS feeds on my site, and it felt like a perfectly reasonable request in the spirit of IndieWeb. This is a statically generated Jekyll site, and I couldn’t really find out-of-the box examples that worked exactly for my site.&lt;/p&gt;

&lt;p&gt;Although, if you’re trying to kill two birds with one stone - that is to add categories and category feeds, you should use the &lt;a href=&quot;https://github.com/jekyll/jekyll-archives&quot;&gt;jekyll-archives&lt;/a&gt; plugin, which seems to be capable of both generating the category pages, and category-specific RSS feeds.&lt;/p&gt;

&lt;p&gt;I already have working and heavily customized categories through the unofficial &lt;a href=&quot;https://github.com/field-theory/jekyll-category-pages&quot;&gt;jekyll-category-pages&lt;/a&gt;, and I needed a custom solution. This solution doesn’t rely on jekyll-category-pages though.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/rosipov-categories.png&quot; alt=&quot;Maybe there are too many RSS icons, I should probably change that. But you get the idea&quot; /&gt;&lt;/p&gt;

&lt;p&gt;My Ruby skills are rusty, so I used Gemini Pro 2.5 to give me a hand with code generation. It took a couple of iterations, but the result is working fine.&lt;/p&gt;

&lt;p&gt;First I added &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_layouts/category_feed.xml&lt;/code&gt; to create a layout:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;---
layout: null
---
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;rss version=&quot;2.0&quot; xmlns:atom=&quot;http://www.w3.org/2005/Atom&quot;&amp;gt;
  &amp;lt;channel&amp;gt;
    &amp;lt;title&amp;gt;{{ site.title | xml_escape }} - {{ page.category | xml_escape }}&amp;lt;/title&amp;gt;
    &amp;lt;description&amp;gt;Recent posts in {{ page.category | xml_escape }} category on {{ site.title | xml_escape }}.&amp;lt;/description&amp;gt;
    &amp;lt;link&amp;gt;{{ &quot;/&quot; | absolute_url }}&amp;lt;/link&amp;gt;
    &amp;lt;atom:link href=&quot;{{ site.url }}{{ site.baseurl }}{{ page.url }}&quot; rel=&quot;self&quot; type=&quot;application/rss+xml&quot; /&amp;gt;
    &amp;lt;pubDate&amp;gt;{{ site.time | date_to_rfc822 }}&amp;lt;/pubDate&amp;gt;
    &amp;lt;lastBuildDate&amp;gt;{{ site.time | date_to_rfc822 }}&amp;lt;/lastBuildDate&amp;gt;
    &amp;lt;generator&amp;gt;Jekyll v{{ jekyll.version }}&amp;lt;/generator&amp;gt;
    {% for post in site.categories[page.category] %}
      &amp;lt;item&amp;gt;
        &amp;lt;title&amp;gt;{{ post.title | xml_escape }}&amp;lt;/title&amp;gt;
        &amp;lt;description&amp;gt;{{ post.content | xml_escape }}&amp;lt;/description&amp;gt;
        &amp;lt;pubDate&amp;gt;{{ post.date | date_to_rfc822 }}&amp;lt;/pubDate&amp;gt;
        &amp;lt;link&amp;gt;{{ post.url | absolute_url }}&amp;lt;/link&amp;gt;
        &amp;lt;guid isPermaLink=&quot;true&quot;&amp;gt;{{ post.url | absolute_url }}&amp;lt;/guid&amp;gt;
        {% for tag in post.tags %}
        &amp;lt;category&amp;gt;{{ tag | xml_escape }}&amp;lt;/category&amp;gt;
        {% endfor %}
        {% for cat in post.categories %}
        &amp;lt;category&amp;gt;{{ cat | xml_escape }}&amp;lt;/category&amp;gt;
        {% endfor %}
      &amp;lt;/item&amp;gt;
    {% endfor %}
  &amp;lt;/channel&amp;gt;
&amp;lt;/rss&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, I added &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_plugins/category_feed_generator.rb&lt;/code&gt; (be sure to customize the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blog/categories&lt;/code&gt; path to your liking):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;module Jekyll
  class CategoryFeedPage &amp;lt; Page
    def initialize(site, base, dir, category)
      @site = site
      @base = base
      @dir = dir
      @name = &quot;#{Jekyll::Utils.slugify(category)}.xml&quot;

      self.process(@name)
      self.read_yaml(File.join(base, &apos;_layouts&apos;), &apos;category_feed.xml&apos;)
      self.data[&apos;category&apos;] = category
    end
  end

  class CategoryFeedGenerator &amp;lt; Generator
    safe true

    def generate(site)
      if site.layouts.key? &apos;category_feed&apos;
        dir = &apos;blog/categories&apos;
        site.categories.each_key do |category|
          site.pages &amp;lt;&amp;lt; CategoryFeedPage.new(site, site.source, dir, category)
        end
      end
    end
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This creates feeds like &lt;a href=&quot;/blog/categories/programming.xml&quot;&gt;/blog/categories/programming.xml&lt;/a&gt; (or whatever URL you used).&lt;/p&gt;

&lt;p&gt;Finally, I added category specific links to the category listing pages and the category index (that part will be specific to how you choose to display your categories): &lt;a href=&quot;/blog/categories/programming.xml&quot;&gt;RSS feed for Programming&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;a href=&quot;/blog/categories/programming.xml&quot;&amp;gt;RSS feed for Programming&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can see the full commit with the changes &lt;a href=&quot;https://github.com/ruslanosipov/ruslanosipov.github.io/commit/8af8814a92877123be8de3e6f307644f6348e099&quot;&gt;here&lt;/a&gt;. Happy Jekyll-ing!&lt;/p&gt;
</description>
        <pubDate>Fri, 06 Jun 2025 04:00:00 +0000</pubDate>
        <link>https://rosipov.com/blog/category-specific-rss-feeds-in-jekyll/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/category-specific-rss-feeds-in-jekyll/</guid>
        
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>Migrating from Octopress to Jekyll</title>
        <description>&lt;p&gt;Back in 2014 I &lt;a href=&quot;https://rosipov.com/blog/abandoning-wordpress-for-octopress/&quot;&gt;abandoned WordPress for Octopress&lt;/a&gt;. It’s been especially amazing for &lt;a href=&quot;https://rosipov.com/blog/static-websites-rule/&quot;&gt;page load speeds&lt;/a&gt;, and I also enjoyed the fact that GitHub Pages are completely free - and I only need to pay for a domain name. Hosting a website can get expensive.&lt;/p&gt;

&lt;p&gt;Octopress was a shortlived framework built on top of Jekyll, focused on blogging and designed to run on top of GitHub Pages. Unfortunately the development stopped in 2015, and now, 10 years later, I couldn’t set it up on a new machine due to most dependencies getting dangerously out of date.&lt;/p&gt;

&lt;p&gt;I chose to migrate to vanilla Jekyll, since it’s a static site generator which is built on top of simple markdown and HTML files. Jekyll’s been around for some time, and I’m hoping Microsoft won’t be shutting down GitHub pages any time soon.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/goodbye-octopress.png&quot; alt=&quot;Saying goodbye to Octopress (granted, it looks almost the same).&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The whole process only took a couple of hours, and I’d like to document some highlights and lowlights. You might find it useful if you’re setting up a new Jekyll blog, or, like me, still have an Octopress blog that needs migrating.&lt;/p&gt;

&lt;h3 id=&quot;fresh-setup&quot;&gt;Fresh setup&lt;/h3&gt;

&lt;p&gt;I went with a fresh Jekyll setup, by installing Jekyll and running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jekyll new blog&lt;/code&gt;. I successfully copied over old &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_posts&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;images&lt;/code&gt;, and ported the relevant parts of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_config.yml&lt;/code&gt; from Octopress to vanilla Jekyll.&lt;/p&gt;

&lt;p&gt;Octopress uses liquid &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{% img %}&lt;/code&gt; tags, which aren’t natively supported in Jekyll. I took the opportunity to convert those to markdown style syntax. I only have a few hundred posts, and I used a Vim macro to convert all &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{% img /foo/bar.png baz %}&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;![baz](/foo/bar.png)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;By default Jekyll comes installed with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minima&lt;/code&gt; theme, which I found to be mostly sufficient for my needs. I was able to override specific theme files by copying them from gem installation location to my blog directory and modifying them. Turned out to be straightforward and customizable. For example, I transferred the way Octopress pagination looks by modifying &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_layouts/home.html&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For backward compatbility, I also had to move RSS feed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/atom.xml&lt;/code&gt; by modifying  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_config.yml&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;feed:
  path: /atom.xml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I could immediately run the site locally with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bundle exec jekyll serve --baseurl=&quot;&quot;&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;missing-functionality&quot;&gt;Missing functionality&lt;/h3&gt;

&lt;p&gt;Two major things were missing straight out of the box: archive and category pages.&lt;/p&gt;

&lt;p&gt;I grew attached to my archive page, and recreating it only took a couple of minutes. All I had to do is add an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;archive.markdown&lt;/code&gt; page to the site’s root directory:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;---
layout: page
title: Archive
navbar: Archive
permalink: /blog/archive/
---
  
{%- assign date_format = site.minima.date_format | default: &quot;%b %-d, %Y&quot; -%}

&amp;lt;div&amp;gt;
  &amp;lt;ul&amp;gt;
    {% for post in site.posts %}
      {% capture this_year %}{{ post.date | date: &quot;%Y&quot; }}{% endcapture %}
      {% unless year == this_year %}
        {% assign year = this_year %}
        &amp;lt;h2 style=&quot;margin-top: 1em;&quot;&amp;gt;{{ year }}&amp;lt;/h2&amp;gt;
      {% endunless %}
      &amp;lt;li&amp;gt;
        &amp;lt;a href=&quot;{{ root_url }}{{ post.url }}&quot; itemprop=&quot;url&quot;&amp;gt;{{ post.title }}&amp;lt;/a&amp;gt;
        &amp;lt;span class=&quot;text-muted&quot;&amp;gt;| 📅 {{ post.date | date: date_format }}&amp;lt;/span&amp;gt;
      &amp;lt;/li&amp;gt;
    {% endfor %}
  &amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Building category support turned out to be messier and more complicated. I didn’t want to write up a custom solution, and ended up with some technical debt I’ll probably have to address in the future (wink-wink, this will never happen).&lt;/p&gt;

&lt;p&gt;I used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jekyll-category-pages&lt;/code&gt; gem, which worked okay-ish. The instructions on &lt;a href=&quot;https://github.com/field-theory/jekyll-category-pages&quot;&gt;field-theory/jekyll-category-pages&lt;/a&gt; are extensive and aren’t too difficult to follow - I appreciated not having to write my own category pages, but I had to:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Stop category pages from being automatically added to the navigation bar.&lt;/li&gt;
  &lt;li&gt;Disable pagination on category pages, because for some reason it really didn’t work with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jekyll-category-pages&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I also added my own basic category index pages by creating &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;categories.markdown&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;---
layout: page
title: Categories
navbar: Categories
permalink: /blog/categories/
---

{% assign category_names = &quot;&quot; | split: &quot;&quot; %}
{% for category in site.categories %}
  {% assign category_names = category_names | push: category[0] %}
{% endfor %}
{% assign category_names = category_names | sort %}
  
&amp;lt;div&amp;gt;
  &amp;lt;ul&amp;gt;
    {% for category in category_names %}
      &amp;lt;li&amp;gt;
        &amp;lt;a href=&quot;{{ root_url }}/{{ site.category_path }}/{{ category | slugify }}&quot;&amp;gt;{{ category }}&amp;lt;/a&amp;gt;
      &amp;lt;/li&amp;gt;
    {% endfor %}
  &amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;github-pages&quot;&gt;GitHub Pages&lt;/h3&gt;

&lt;p&gt;While &lt;a href=&quot;https://docs.github.com/en/pages/setting-up-a-github-pages-site-with-jekyll&quot;&gt;GitHub Pages documentation&lt;/a&gt; is extensive, getting Jekyll to work with GitHub Pages took longer than I’d like to admit. Specifically, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Gemfile&lt;/code&gt; generated by running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jekyll new blog&lt;/code&gt; misleadingly tells you to comment away the latest version of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jekyll&lt;/code&gt; gem and instead use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;github-pages&lt;/code&gt; gem:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Happy Jekylling!
gem &quot;jekyll&quot;, &quot;~&amp;gt; 4.4.1&quot;
# If you want to use GitHub Pages, remove the &quot;gem &quot;jekyll&quot;&quot; above and
# uncomment the line below. To upgrade, run `bundle update github-pages`.
# gem &quot;github-pages&quot;, group: :jekyll_plugins
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You don’t want to do that, oh no. Because the default GitHub Pages gem is stuck in the past on the 3rd version of Jekyll (and at the time of writing we’re on version 4), which caused all kind of hidden problems - including the fact that my URL slugs silently weren’t getting generated right. I switched back on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jekyll&lt;/code&gt; gem and set up a custom GitHub action to deploy the site:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;name: Deploy Jekyll site to Pages

on:
  push:
    branches: [&quot;master&quot;]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

permissions:
  contents: read
  pages: write
  id-token: write

concurrency:
  group: &quot;pages&quot;
  cancel-in-progress: false

jobs:
  # Build job
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Setup Ruby
        # https://github.com/ruby/setup-ruby/releases/tag/v1.207.0
        uses: ruby/setup-ruby@4a9ddd6f338a97768b8006bf671dfbad383215f4
        with:
          ruby-version: &apos;3.1&apos; # Not needed with a .ruby-version file
          bundler-cache: true # runs &apos;bundle install&apos; and caches installed gems automatically
          cache-version: 0 # Increment this number if you need to re-download cached gems
      - name: Setup Pages
        id: pages
        uses: actions/configure-pages@v5
      - name: Build with Jekyll
        run: bundle exec jekyll build --baseurl &quot;$&quot;
        env:
          JEKYLL_ENV: production
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3

  # Deployment job
  deploy:
    environment:
      name: github-pages
      url: $
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Don’t forget to set “Build and deployment source” to “GitHub pages” in the repository settings to actually use the action.&lt;/p&gt;

&lt;p&gt;My Octopress blog was set up in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;source&lt;/code&gt; Git branch, and content was generated into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; branch. I wanted to change that to have the source in the master branch (the action above won’t work without that), and I was able to replace my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;source&lt;/code&gt; with the following set of commands:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    git checkout master
    git pull
    git checkout source
    git merge -s ours master --allow-unrelated-histories
    git checkout master
    git merge source
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We merge the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; branch into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;source&lt;/code&gt; using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ours&lt;/code&gt; merge strategy (effectively ignoring the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; branch history), and then merge that back into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;positive-experience&quot;&gt;Positive experience&lt;/h3&gt;

&lt;p&gt;All in all migrating to Jekyll has been a great experience, which is a testament to Jekyll community’s dedication to thorough documentation. Knowing that Jekyll is a mature, maintained, and documented project, and that GitHub Pages infrastructure is reliable and supported, provides a sense of stability. I hope this results in Jekyll and GitHub Pages becoming a (reasonably) future-proof platform for my blog. But let’s check back in in 10 years - see you in 2035?&lt;/p&gt;

</description>
        <pubDate>Wed, 19 Mar 2025 20:00:00 +0000</pubDate>
        <link>https://rosipov.com/blog/migrating-from-octopress-to-jekyll/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/migrating-from-octopress-to-jekyll/</guid>
        
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>Static websites rule!</title>
        <description>&lt;p&gt;I hope you’ve noticed that navigating to this page was quick (let’s hope that the Internet Gods are kind to me, and nothing stood in the way of you accessing this page). In fact, most pages on my blog - hopefully including this one - should render in under a second. I didn’t put any work into optimizing this site, and it’s not a boast, nor is it a technological marvel - this is just a good old fashioned static website.&lt;/p&gt;

&lt;p&gt;If this is new to you - static website is just what it sounds like - static HTML and CSS files, sometimes with some light JavaScript sprinkled throughout. There’s no server side processing – the only bottlenecks are the host server speed, recipient’s connection speed, and the browser rendering speed. Page is stored as is, and is sent over as soon as it’s requested. This is how the Internet used to be in late 90s and early 2000s (with eclectic web design to boot, of course).&lt;/p&gt;

&lt;p&gt;I think static websites are cool and aren’t used nearly enough, especially for websites that are, well, static. Think to the last website you’ve visited to read something - maybe a news site, or maybe a blog. Now did it take at least a couple of seconds for them to load? Likely. Did their server have to waste unnecessary cycles putting together a page for you? Most definitely. Now, contrast this with your experience with a static website like this one. Here’s the result from &lt;a href=&quot;https://pagespeed.web.dev/&quot;&gt;pagespeed.web.dev&lt;/a&gt; for this page:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/rosipov-page-speed-test.png&quot; alt=&quot;A screenshot with page speed test for rosipov.com (this website). It displays: first contentful paint: 0.8 s; largest contentful paint: 0.9 s; total blocking time: 0 ms; cumulative layout shift: 0.007; speed index: 0.7 s.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Every render complete in under a second, and I didn’t have to put in any work into optimizing my website.&lt;/p&gt;

&lt;p&gt;This site is built on a (now unsupported) &lt;a href=&quot;http://octopress.org/&quot;&gt;Octopress&lt;/a&gt;, which is itself built on top of &lt;a href=&quot;https://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt;. You write pages in Markdown, generate web pages using a pre-made template, and deploy the resulting pages to a hosting provider. In fact, &lt;a href=&quot;https://pages.github.com/&quot;&gt;GitHub Pages&lt;/a&gt; allow you to host your static website for free, and you can have a third party platform like &lt;a href=&quot;https://disqus.com/&quot;&gt;Disqus&lt;/a&gt; provide comment support.&lt;/p&gt;

&lt;p&gt;Static websites work great for portfolios, blogs, and websites that don’t rely on extensive common manipulation. They’re more secure (no backend to hack), simple to build and maintain, very fast even without optimization, and are natively SEO friendly (search engines are great at understanding static pages). Static websites are cheap to run - I only pay for a domain name for this site (under $20 a year).&lt;/p&gt;

&lt;p&gt;If you have a blog or a portfolio and you’re using an overly complicated content management system to write - consider slimming down. &lt;a href=&quot;https://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt; (or many of its alternatives) offers a number of pre-made off-ramps for major CMS users, is easy to set up, and is straightforward to work with. Can’t recommend enough - static websites rule!&lt;/p&gt;

</description>
        <pubDate>Thu, 27 Jul 2023 15:00:00 +0000</pubDate>
        <link>https://rosipov.com/blog/static-websites-rule/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/static-websites-rule/</guid>
        
        
        <category>Programming</category>
        
        <category>Technology</category>
        
      </item>
    
      <item>
        <title>Making a packing spreadsheet</title>
        <description>&lt;p&gt;Being the unique person I am, I love traveling. Oftentimes I end up getting deep into trying to optimize my packing methods. There are dozens of tools online designed to help with this exact thing (services like &lt;a href=&quot;http://lighterpack.com&quot;&gt;Lighterpack&lt;/a&gt; or &lt;a href=&quot;http://geargrams.com&quot;&gt;GearGrams&lt;/a&gt;). But, being handy with code, I decided to dabble in the subject on my own.&lt;/p&gt;

&lt;p&gt;One of the most important things in packing is the overall weight of the pack, and I always want to know what type of things are the heaviest. I also want to be able to run random queries on my data, whatever it is that I’m trying to learn. I want to have an inventory of items (backpacks, clothes, storage solutions) which I can plug in and out of a spreadsheet to see how the resulting picture changes on the go. Working with software as my day job, I’d also like for the solution to be automated whenever possible.&lt;/p&gt;

&lt;p&gt;Google Spreadsheets turned out to be the perfect solution, providing the ability to quickly sum up the weight of my things and output insights about the data.&lt;/p&gt;

&lt;h2 id=&quot;final-result&quot;&gt;Final Result&lt;/h2&gt;

&lt;p&gt;Here’s a &lt;a href=&quot;https://docs.google.com/spreadsheets/d/1qDhMoVmmTroM-eN0MZIU2PzE5YucsyPhbuPZPDGhemM/edit#&quot;&gt;link to the spreadsheet&lt;/a&gt;, I encourage the reader to copy and play around with in anyway you see fit.&lt;/p&gt;

&lt;p&gt;Here’s the final result for a multi-day trip I will have for this year. As you can see, my pack weighs around 3 kilograms or a bit over 6 freedom units (not including water). My recently purchased Nintendo Switch is the heaviest item (and it’s worth every gram as it makes flying tolerable), but clothes take up most of the weight:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/packing-spreadsheet.png&quot; alt=&quot;A screenshot of a packing spreadsheet.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I use indentation levels to show that some items are contained within other items. This also lets me calculate the absolute and relative weights of a whole container with everything inside of it (see fields labeled “Container” and “Percentage”).&lt;/p&gt;

&lt;p&gt;The “Weight” and the “Breakdown” fields indicate absolute and relative item weight respectively, which accounts for quantity of the item (quantity defaults to 1 if not explicitly set). Weight-related fields are color coded from lightest items in green to heaviest items in red.&lt;/p&gt;

&lt;p&gt;Categories are used to group items and execute queries on the data and learn insights like these:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/packing-spreadsheet-weight-chart.png&quot; alt=&quot;A chart representing the weight of each category of items relative to a weight of the whole pack.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;There’s a separate sheet where I enter item names, categories, and weights, which I then use to automatically populate values above and autofill item names in the primary sheet:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/packing-spreadsheet-inventory.png&quot; alt=&quot;A screenshot of an inventory tab of the packing spreadsheet.&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;the-technical-details&quot;&gt;The Technical Details&lt;/h2&gt;

&lt;p&gt;I haven’t worked with Google Spreadsheets (or Excel for that matter) a lot in the past, but with an access to clear documentation (and a hundred of web searches later) it was straightforward to get the hang of the it.&lt;/p&gt;

&lt;p&gt;I started off by manually populating the final result sheet, manually adjusting formulas for Container/Percentage cells, as I had no idea how I would detect the indentation yet. I like when things look pretty, so I applied conditional formatting rules right away, and the looks of the sheet really haven’t changed throughout the process.&lt;/p&gt;

&lt;p&gt;Next, I created an inventory sheet, which I wanted to use as a source of data in the resulting sheet. A few Google searches and some trial &amp;amp; error resulted in a lookup formula:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;=ArrayFormula(
 IF(
   NOT(ISBLANK($B2)),
   INDEX(InventoryCategories, MATCH($B2, InventoryItems, 0)),
   IF(
     NOT(ISBLANK($C2)),
     INDEX(InventoryCategories, MATCH($C2, InventoryItems, 0)),
     INDEX(InventoryCategories, MATCH($D2, InventoryItems, 0))
   )
  )
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ArrayFormula&lt;/code&gt; is necessary in order to create arrays on the fly without printing intermediate results in the spreadsheet. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;InventoryItems&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;InventoryCategories&lt;/code&gt; are named ranges referring to item names and categories in the inventory sheet. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MATCH&lt;/code&gt; finds an index of a first occurrence of the item name in the sheet, and retrieves corresponding category name. An item weight is retrieved by the exact same principle.&lt;/p&gt;

&lt;p&gt;Trying to find the container weight took a lot more time, and resulted in a lot more headache. Solution for handling indentation in Google Spreadsheets wasn’t as elegant as I would have hoped for, but it got the job done:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;=ArrayFormula(
     SUM(
       $I2:INDIRECT(
         CONCATENATE(
           &quot;$I&quot;,
           ROW() + IF(
             NOT(ISBLANK($B2)),
             MATCH(FALSE, ISBLANK($B3:$B), 0),
             MATCH(FALSE, ISBLANK($C3:$C), 0)
           ) - 1
         )
       )
     )
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The formula above finds the first non-empty cell in a column. It starts searching from the next row (for example, for an item on a second row, we look at the third row and below). After it knows which row first non-empty cell is in, the formula turns it into a string (column $I contains item weights) and use it as an upper bound of a sum of the weights. Finished formula is a bit longer (it adds sugar to only display the number when needed), and if you’re interested - you can look it up in the spreadsheet.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/packing-spreadsheet-indentation.png&quot; alt=&quot;A screenshot used for explaining indentation logic.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;For example, in the screenshot above, the formula will start looking at cells in a column right after the “Packing cube”. As soon as it finds a non-empty cell (“Nintendo Switch case”), the formula will determine this row to be an upper boundary. The formula then will sum weights starting with a “Packing cube” row, and up to but not including “Nintendo Switch case” row.&lt;/p&gt;

&lt;p&gt;The rest involved many small tweaks, adding pretty colors, hiding N/A errors and zeroes, and trying to find the perfect shade for column borders.&lt;/p&gt;

&lt;p&gt;And, since you made it this far, here’s how the numbers above look in the real world:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/cleveland-trip-backpack-on-off.png&quot; alt=&quot;Side by side pictures of a packed backpack: open and closed.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Hopefully you found this useful, or at least somewhat entertaining. There’s a lot of room for improvement, and I aimed to provide a framework and a few basic ideas for building a spreadsheet to accommodate one’s twisted ultralight needs.&lt;/p&gt;

</description>
        <pubDate>Mon, 26 Mar 2018 00:00:00 +0000</pubDate>
        <link>https://rosipov.com/blog/making-a-packing-spreadsheet/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/making-a-packing-spreadsheet/</guid>
        
        
        <category>Programming</category>
        
        <category>Travel</category>
        
      </item>
    
      <item>
        <title>Automating Octorpress publishing</title>
        <description>&lt;p&gt;I really like Octopress. It builds on top of Jekyll to address certain rough edges, and provides ready to go lighting fast blogging platform. It’s easily extendible if you know how to code (thanks to a rather clean and well organized code base), and posts are just plain Markdown files.&lt;/p&gt;

&lt;p&gt;One issue though - I need to be near a computer to publish and preview the article. This becomes difficult if I’m traveling with, say, a tablet.&lt;/p&gt;

&lt;p&gt;I have a low end AWS Lightsail instance I use for writing and publishing, but it’s not always fun to write when SSHing into a server, and I often write offline - making it even more difficult to move files between where I write and where I publish. And managing images is a nightmare. To resolve this, I set up a few directories I use in Dropbox, and wrote a few scripts to move things around when needed.&lt;/p&gt;

&lt;p&gt;Here’s a directory structure in Dropbox:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;- blog/
  - posts/
    - 2017-11-20-automatic-octopress-publishing.markdown
  - img/
    - input/
      - a-picture-of-a-flower.jpg
    - output/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I put Markdown files in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dropbox/blog/posts/&lt;/code&gt; (and numerous offline editors sync with Dropbox - I’m writing this with &lt;a href=&quot;https://stackedit.io/app&quot;&gt;StackEdit&lt;/a&gt;, and I use &lt;a href=&quot;https://ia.net/writer/&quot;&gt;iA Writer&lt;/a&gt; on my tablet). I add my images to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Dropbox/img/input/&lt;/code&gt;. I  tend to strip metadata from my images and resize them to fit the maximum page width (I don’t really care for high resolution pictures, speed is preferred over ability to zoom into a picture). For this, two tools are needed:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo apt-get install imagemagick exiftool
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When I’m done writing or want to preview an article, I SSH into my AWS Lightsail instance and run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sync.sh&lt;/code&gt;, a small script which moves posts to a proper directory, processes images and places them in the desired location, as well as starts Octopress instance (this way I can preview my blog on the AWS Lightsail instance). Contents of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sync.sh&lt;/code&gt; (don’t forget to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chmod +x&lt;/code&gt;):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/bin/bash
cd $HOME/Dropbox/blog/img/input
mogrify -resize 832x620 -quality 100 -path $HOME/Dropbox/blog/img/output *.jpg
exiftool -all= $HOME/Dropbox/blog/img/output/*.jpg
cp $HOME/Dropbox/blog/posts/*.markdown $HOME/blog/source/_posts
cp $HOME/Dropbox/blog/img/output/*.jpg $HOME/blog/source/images/posts
cd $HOME/blog
rake generate
rake preview
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I run the above script every time I want to preview the site. I’m sure it’s easy to set up a daemon to watch for changes in the Dropbox folders, but I don’t see the need for that yet. Also, I just statically resize images to a particular resolution (832x620) since all of the pictures I upload have the same aspect ratio, I’m sure there’s a way to calculate that number on the fly for this script to work with different aspect ratios.&lt;/p&gt;

&lt;p&gt;Lastly, when I deployed and committed my changes (still commit and deploy manually out of a habit), I run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;archive.sh&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/bin/bash
mv $HOME/Dropbox/blog/posts/*.markdown $HOME/Dropbox/blog/published
rm $HOME/Dropbox/blog/img/input/*
rm $HOME/Dropbox/blog/img/output/*
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s not much, but enough to save some manual labor involved in publishing to Octopress.
&lt;!--stackedit_data:
eyJoaXN0b3J5IjpbMTY3OTE1ODIzNl19
--&gt;&lt;/p&gt;
</description>
        <pubDate>Tue, 14 Nov 2017 15:00:00 +0000</pubDate>
        <link>https://rosipov.com/blog/automating-octopress-publishing/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/automating-octopress-publishing/</guid>
        
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>Mob level distribution</title>
        <description>&lt;p&gt;Distributing mobs in a dungeon based on player’s level (or some dungeon level
difficulty factor) was somewhat straightforward, but I would still like to
document the progress. I needed to place a mob that’s somewhat within the
difficulty level I want, plus minus a few difficulty levels to spice it up.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/roguelike-leveled-mob-distribution.png&quot; alt=&quot;Random mob distribution in roguelike dungeon.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Above you can see three rats, three cats, a dog (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;r&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;d&lt;/code&gt;, all level 1), a
farmer (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt;, level 2), and a lonely bandit (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b&lt;/code&gt;, level 3) in a level 1 dungeon.&lt;/p&gt;

&lt;p&gt;Without going straight into measure theory, I generated intervals for each mob
based on the diff of desired level and their level, and then randomly selected a
point within the boundaries. Here’s the abstract code:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import bisect
import random


def get_random_element(data, target, chance):
    &quot;&quot;&quot;Get random element from data set skewing towards target.

    Args:
        data   -- A dictionary with keys as elements and values as weights.
                  Duplicates are allowed.
        target -- Target weight, results will be skewed towards target
                  weight.
        chance -- A float 0..1, a factor by which chance of picking adjacent
                  elements decreases (i.e, with chance 0 we will always
                  select target element, with chance 0.5 probability of
                  selecting elements adjacent to target are halved with each
                  step).

    Returns:
        A random key from data with distribution respective of the target
        weight.
    &quot;&quot;&quot;
    intervals = []  # We insert in order, no overlaps.
    next_i = 0
    for element, v in data.iteritems():
        d = max(target, v) - min(target, v)
        size = 100
        while d &amp;gt; 0:  # Decrease chunk size for each step of `d`.
            size *= chance
            d -= 1
        if size == 0:
            continue
        size = int(size)
        intervals.append((next_i, next_i + size, element))
        next_i += size + 1
    fst, _, _ = zip(*intervals)
    rnd = random.randint(0, next_i - 1)
    idx = bisect.bisect(fst, rnd)  # This part is O(log n).
    return intervals[idx - 1][2]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, if I test the above for, say, a 1000000 iterations, with a chance of 0.5
(halving probability of selecting adjacent elements with each step), and 2 as a
target, here’s the distribution I end up with:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;target, chance, iterations = 2, 0.5, 1000000

data = collections.OrderedDict([  # Ordered to make histogram prettier.
    (&apos;A&apos;, 0), (&apos;B-0&apos;, 1), (&apos;B-1&apos;, 1), (&apos;C&apos;, 2), (&apos;D&apos;, 3), (&apos;E&apos;, 4),
    (&apos;F&apos;, 5), (&apos;G&apos;, 6), (&apos;H&apos;, 7), (&apos;I&apos;, 8), (&apos;J&apos;, 9),
])

res = collections.OrderedDict([(k, 0) for k, _ in data.iteritems()])

# This is just a test, so there&apos;s no need to optimize this for now.
for _ in xrange(iterations):
    res[get_random_element(data, target, chance)] += 1

pyplot.bar(
    range(len(res)), res.values(), width=0.7, align=&apos;center&apos;, color=&apos;green&apos;)
pyplot.xticks(range(len(res)), res.keys())
pyplot.title(
    &apos;iterations={}, target={}, chance={}&apos;.format(
        iterations, target, chance))
pyplot.show()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/roguelike-mob-distribution-chance-05.png&quot; alt=&quot;Distribution histogram: 1000000 iterations, 0.5 chance, and 2 as a target.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You can see elements B-0 and B-1 having roughly the same distribution, since
they have the same weight.&lt;/p&gt;

&lt;p&gt;Now, if I decrease the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chance&lt;/code&gt;, likelihood of target being selected increases,
while likelihood of surrounding elements being selected decreases:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/roguelike-mob-distribution-chance-033.png&quot; alt=&quot;Distribution histogram: 1000000 iterations, 0.33 chance, and 2 as a target.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I works the opposite way as well, increasing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chance&lt;/code&gt; decreases likelihood
of the target being selected and increases the probability for surrounding
elements.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/roguelike-mob-distribution-chance-09.png&quot; alt=&quot;Distribution histogram: 1000000 iterations, 0.9 chance, and 2 as a target.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;For the sake of completeness, it works with 0 chance of surrounding elements being picked:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/roguelike-mob-distribution-chance-0.png&quot; alt=&quot;Distribution histogram: 1000000 iterations, 0 chance, and 2 as a target.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And an equal chance of picking surrounding elements:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/roguelike-mob-distribution-chance-1.png&quot; alt=&quot;Distribution histogram: 1000000 iterations, 1 chance, and 2 as a target.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;After playing around with the configuration in Jupyter Notebook, I cleaned up
the algorithm above and included it into mob placement routine.&lt;/p&gt;
</description>
        <pubDate>Sun, 02 Oct 2016 00:15:12 +0000</pubDate>
        <link>https://rosipov.com/blog/mob-level-distribution/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/mob-level-distribution/</guid>
        
        
        <category>Gamedev</category>
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>Spawning evenly distributed mobs</title>
        <description>&lt;p&gt;After generating a few &lt;a href=&quot;https://rosipov.com/blog/randomly-generated-dungeons/&quot;&gt;good looking random dungeons&lt;/a&gt;, I was puzzled with
randomly placing mobs on resulting maps. To make it fair (and fun) for the
player mobs should be evenly distributed.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/dungeon-mob-placement.png&quot; alt=&quot;Dungeon with randomly placed mobs.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The obvious idea was to pick coordinates randomly within the rectangular map
boundaries, and then place mobs if they have floor underneath them. But this way
I lose control of the number of mobs and risk having a chance of not placing any
mobs at all. Plus, dungeons with bigger surface area would get more mobs - which
sounds somewhat realistic, but not entirely what I was aiming for.&lt;/p&gt;

&lt;p&gt;I could improve on the above by rerunning enemy placement multiple times and
select the most favorable outcome - but the solution would be rather naive.&lt;/p&gt;

&lt;p&gt;To have control over the number of mobs I decided to place them as I generate
the rooms of the dungeon. There’s a trick one can use to get a random element
with equal probability distribution from a sequence of an unknown size:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import random


def get_random_element(sequence):
    &quot;&quot;&quot;Select a random element from a sequence of an unknown size.&quot;&quot;&quot;
    selected = None
    for k, element in enumerate(sequence):
        if random.randint(0, k) == 0:
            selected = element
    return selected
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With each iteration the chance of the current element to become a selected item
is 1 divided by number of elements seen so far. Indeed, a probability of an
element being selected out of a 4-item sequence:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1 * (1 - 1/2) * (1 - 1/3) * (1 - 1/4) = 1/2 * 2/3 * 3/4 = 6/30 = 1/4 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now all I had to do is to modify this to account for multiple mob placement.
Here’s a generalized function above which accounts for selecting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt; elements
from the sequence with even distribution.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import random


def get_random_element(sequence, n):
    &quot;&quot;&quot;Select n random elements from a sequence of an unknown size.&quot;&quot;&quot;
    selected = [None for _ in range(n)]
    for k, element in enumerate(sequence):
        for i in range(n):
            if random.randint(0, k) == 0:
                selected[i] = element
    return selected
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I incorporated logic above into the room generation code, accounted for
duplicates, and ended up with decent distribution results.&lt;/p&gt;

</description>
        <pubDate>Fri, 30 Sep 2016 18:06:16 +0000</pubDate>
        <link>https://rosipov.com/blog/spawning-evenly-distributed-mobs/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/spawning-evenly-distributed-mobs/</guid>
        
        
        <category>Gamedev</category>
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>Randomly generated dungeons</title>
        <description>&lt;p&gt;After playing with random dungeon generation for a bit, I seem to be satisfied
with the results:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/random-dungeon-1.png&quot; alt=&quot;A randomly generated ASCII-dungeon.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The above is displayed using ADOM notation - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#&lt;/code&gt; represents a wall, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.&lt;/code&gt; is a
floor tile, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; is meant to be a closed door. After fiddling about with a
few random dungeon generation ideas, I settled with the following.&lt;/p&gt;

&lt;h2 id=&quot;the-algorithm&quot;&gt;The algorithm&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;Start with a random point on a canvas.&lt;/li&gt;
  &lt;li&gt;Create a room with random width and height. Don’t worry about walls yet.&lt;/li&gt;
  &lt;li&gt;Select a few points on the sides of the room, put those in a stack. Save the
direction in which the potential doors would point.&lt;/li&gt;
  &lt;li&gt;Go through the stack, and try to add a room or a corridor (corridor is just a
room with a width or a height of 1). Higher chance of corridors seems to look
better and results in those wiggly passageways.
    &lt;ol&gt;
      &lt;li&gt;Try to add a room a few dozen times with different random configurations.
If no luck - give up and grab a new item from the stack. If couldn’t
generate a continuation to the corridor - mark it as a loose end, we’ll
clean those up later.&lt;/li&gt;
      &lt;li&gt;If a room was added successfully - add a door where it connects to the
previous room/corridor. Add a floor section if it’s a corridor connecting
to another corridor.&lt;/li&gt;
      &lt;li&gt;At this point one ends up with quite a few interconnected corridors,
merged rooms, and all kinds of fun surroundings (my desired goal).&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Do the above until the stack is empty or a desired number of rooms has been
generated.&lt;/li&gt;
  &lt;li&gt;Clean up the loose ends from step 4.1. Remove loose corridor segments one by
one until intersection with another room/corridor is detected.&lt;/li&gt;
  &lt;li&gt;Add walls around the rooms and corridors, while also cleaning up any extra
doors we may have left behind when creating merged corridors or rooms.
    &lt;ol&gt;
      &lt;li&gt;I simply used slightly modified depth first search starting inside any
room and drawing walls wherever I could find floor/door not connected to
anything.&lt;/li&gt;
      &lt;li&gt;When encountering a door - check if it’s surrounded by walls or doors from
the opposite sides. If not - remove the door and replace it with a floor
tile. If any doors were adjucent to the removed door - requeue the door
check on them.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Perform steps 1-7 a few hundred times, saving the resulting dungeons each
time. Pick the best candidate with the most desired features - like a number
of rooms, breadth, square footage, longest corridors, etc.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A more detailed explanation of the steps is below. For now, here are a few more
dungeons generated using this method:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/random-dungeon-2.png&quot; alt=&quot;A randomly generated ASCII-dungeon.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/random-dungeon-3.png&quot; alt=&quot;A randomly generated ASCII-dungeon.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/random-dungeon-4.png&quot; alt=&quot;A randomly generated ASCII-dungeon.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I think dungeon generation is far more art than science, and I had a lot of fun
tweaking all the different input parameters:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Room size boundaries.&lt;/li&gt;
  &lt;li&gt;Corridor lengths.&lt;/li&gt;
  &lt;li&gt;Frequency of corridor occurrences.&lt;/li&gt;
  &lt;li&gt;Number of exits from the room.&lt;/li&gt;
  &lt;li&gt;Number of room generation attempts.&lt;/li&gt;
  &lt;li&gt;Number of dungeon generation attempts.&lt;/li&gt;
  &lt;li&gt;Final dungeon picking heuristics.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Last item on the list is the most interesting one - with few hundred dungeons as
an input, picking the right one is rather important. I ended up settling on
using max priority queue with a rough surface area of the dungeon as a key
(it’s more of a breadth, really - how wide and tall it is). Then I’d sift
through some top results and pick the one with the most rooms available. This
results in the most fun-looking map which feels up most of the screen, while
still usually not being too cluttered.&lt;/p&gt;

&lt;p&gt;Here’s a breakdown of a simple scenario:&lt;/p&gt;

&lt;h3 id=&quot;steps-1-and-2&quot;&gt;Steps 1 and 2&lt;/h3&gt;

&lt;p&gt;Pick a random spot on a canvas and generate a room of random size (4 x 3):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;....
....
....
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;step-3&quot;&gt;Step 3&lt;/h3&gt;

&lt;p&gt;Select potential spots for doors, let’s label them 1, 2, 3.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;....2
....
....1
  3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I went for a uniform distribution by unfolding the rectangle and folding it back
in to get a proper coordinate on the perimeter. Now, stack contains coordinates
of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[1, 2, 3]&lt;/code&gt; (along with the directions in which they are pointing).&lt;/p&gt;

&lt;h3 id=&quot;steps-4-and-5&quot;&gt;Steps 4 and 5&lt;/h3&gt;

&lt;p&gt;Add a room or a corridor to a connector number 3. We’ll be adding the room to
the right of number 3. Let’s assume random sends a corridor of length 5 our way.
We’re happy with the corridor pointing either up, down, or right - so we let the
random decide again: up.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;     4
     .
     .
....2.
.... .
....3.
  1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We add the end of the corridor to the stack as number 4 (now &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[1, 2, 4]&lt;/code&gt;). We
also mark 4 as a loose end, in case we end up not adding a room to it. Dangling
corridors are never pretty.&lt;/p&gt;

&lt;p&gt;Now, to replace number 3 with a door:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;     4
     .
     .
....2.
.... .
....+.
  1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Adding another random corridor of length 2 to the point 4, pointing right.
Replace number 4 with a floor segment, since point 4 was the end of another
corridor. Remove point 4 from loose ends, add point 5.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;     ...5
     .
     .
....2.
.... .
....+.
  1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Take point 5, generate a room of size 3 x 6. 5 becomes a door. Loose ends list
is empty.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;     ...+...
     .   ...
     .   ...
....2.   ...
.... .   ...
....+.   ...
  1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For simplicity’s sake, let’s assume we don’t want any more exits from this room.
Back to the stack of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[1, 2]&lt;/code&gt;. Point 2 seem to not have much room for growth.
After a few unsuccessful attempts to place a room or a corridor there, we give
up:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;     ...+...
     .   ...
     .   ...
.... .   ...
.... .   ...
....+.   ...
  1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now for point 1: we get another corridor of length 3. Point 6 is now added to
the loose ends list.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;     ...+...
     .   ...
     .   ...
.... .   ...
.... .   ...
....+.   ...
  +
  .
  .
  .
  6
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s assume we run out of space and can’t add anything to the end of 6. We’re
done generating the dungeon. Our stack is empty, and our loose ends contains
coordinates of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;6&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;step-6&quot;&gt;Step 6&lt;/h3&gt;

&lt;p&gt;Start with the loose end, and remove items one by one until a tile with multiple
neighbors is encountered:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;     ...+...
     .   ...
     .   ...
.... .   ...
.... .   ...
....+.   ...
  X
  X
  X
  X
  X
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Viola:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;     ...+...
     .   ...
     .   ...
.... .   ...
.... .   ...
....+.   ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;steps-7-and-8&quot;&gt;Steps 7 and 8&lt;/h3&gt;

&lt;p&gt;There are no rogue doors in this scenario, so all we need to do is add  the
walls:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;     #########
     #...+...#
     #.###...#
######.# #...#
#....#.# #...#
#....#.# #...#
#....+.# #...#
######## #####
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;All of the steps above should be repeated a few hundred times with different
dungeons, and then the best dungeon should be picked as a final one.&lt;/p&gt;

&lt;p&gt;Did I miss anything? Was cleaning up “loose ends” too much of a hack? What
should have I done differently?&lt;/p&gt;
</description>
        <pubDate>Thu, 29 Sep 2016 23:26:32 +0000</pubDate>
        <link>https://rosipov.com/blog/randomly-generated-dungeons/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/randomly-generated-dungeons/</guid>
        
        
        <category>Gamedev</category>
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>Contributing to an existing Octopress blog</title>
        <description>&lt;p&gt;I had to download my Octopress blog to a new machine today and the process of
setting up didn’t go as smoothly as I expected. At the end of the day the setup
turned out to be simple, and here are the steps:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone -b source https://github.com/username/username.github.io myblog
cd myblog
git clone https://github.com/username/username.github.io _deploy
bundle install
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In a nutshell, you have to manually add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_deploy&lt;/code&gt; folder set to track &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt;
branch of your Octopress repository. Otherwise &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rake deploy&lt;/code&gt; command fails.&lt;/p&gt;

&lt;p&gt;Happy writing!&lt;/p&gt;
</description>
        <pubDate>Wed, 17 Dec 2014 05:09:58 +0000</pubDate>
        <link>https://rosipov.com/blog/contributing-to-an-existing-octopress-blog/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/contributing-to-an-existing-octopress-blog/</guid>
        
        <category>octopress</category>
        
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>One more argument for 80 character limit</title>
        <description>&lt;p&gt;Limiting code to 80 (or 100 or 120) characters per line. It’s a well-known
topic, and there’s an overall consensus on the subject, not counting occasional
questions by newbies and odd cases. Most established tech companies have their
own line length guidelines. These are often dependent on a language, such as in
the case of Google with their 80 character Python and 100 character Java limits.&lt;/p&gt;

&lt;p&gt;In this article, I won’t be advocating all the usual arguments, such as easier
diff with version control software, or the ability to stack windows side by side
on wide screens. No, I believe that battle to be won quite a long time ago, the
topic is now closed. But something I didn’t find mentioned in any of the
discussions is an interesting point from the world of writers and designers.&lt;/p&gt;

&lt;p&gt;Ever since I started being interested in improving my writing skills, I found
article after article mention the importance of line length in reading.
Interestingly enough, this issue was raised in a world of literature. It had
been resolved long before programmers were fascinated with the desire to use up
rapidly expanding screen real estate.&lt;/p&gt;

&lt;p&gt;I am talking about something known as “measure” in typography. It seems to be
the reason newspapers use narrow columns, or books leave such vast margins
around the text on a page. Here’s an exempt from the &lt;a href=&quot;http://en.wikipedia.org/wiki/Measure_(typography)&quot;&gt;Wikipedia article&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Measure (or sometimes “The Measure”) in typography is the length of a line of
text. For a single-column design measure should ideally lie between 40 &amp;amp; 80
characters. Many typographers consider the perfect measure to be 65
characters. If the lines are too short then the text becomes disjointed, if
they are too long the content loses rhythm as the reader searches for the
start of each line. Punctuation should preferably hang outside the measure.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Most programming languages use special operators and keywords, which can be
considered “punctuation”. Some languages are more verbose (use more
punctuation), and some aren’t. If you remove punctuation, the 80/100/120
character limit perfectly fits the standard time-honed “measure”.&lt;/p&gt;

&lt;p&gt;Maybe I can use this as an additional argument the next time I have to explain
to a junior new hire why the character limits are so strictly enforced.&lt;/p&gt;

</description>
        <pubDate>Wed, 30 Jul 2014 06:00:04 +0000</pubDate>
        <link>https://rosipov.com/blog/one-more-argument-for-80-character-limit/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/one-more-argument-for-80-character-limit/</guid>
        
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>Abandoning WordPress for Octopress</title>
        <description>&lt;p&gt;I finally did it! I’ve left the dark corners of WordPress in favor of
&lt;a href=&quot;http://octopress.org&quot;&gt;Octopress&lt;/a&gt;, which seem to be the best system for my blogging needs.&lt;/p&gt;

&lt;h2 id=&quot;why-the-migration&quot;&gt;Why the migration?&lt;/h2&gt;

&lt;p&gt;WordPress was a great host for me at one point - the community is fun and no
work is required for setup (I would rather not waste time fiddling with my blog
too much). But a number of things are off-putting:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I don’t like WYSIWYG editors and I don’t like web editors. I try to use my
favorite editor for everything, including mail, documentation, note taking.
Even though WordPress allowed me to write my posts using Markdown, I still
didn’t like not being able to use my favorite editor or environment.&lt;/li&gt;
  &lt;li&gt;Storing all the entries in a MySQL database is not favorable. I am writing
text, why would I pick any other format to store what I wrote?&lt;/li&gt;
  &lt;li&gt;Over the years my blog became increasingly slow, and in order to have a
reasonably fast site I needed to pay quite a sum of money. I am not ready for
such a commitment, since I only occasionally update this blog.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the other hand, Octopress (which is based on Jekyll, a static site
generator) has all of these concerns covered:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I can write by creating simple Markdown documents. It doesn’t matter where I
write, or how I write. This enables me to use an editor of my choice.&lt;/li&gt;
  &lt;li&gt;Plain text is universal. It can be viewed by a human, edited in any piece of
software, printed out, emailed, piped to a Linux program - just about
anything really.&lt;/li&gt;
  &lt;li&gt;Static sites are ridiculously fast. There’s no preprocessing and no
rendering.  The only real speed limit is network latency. In addition, GitHub
lets you host static sites for free. What else could you ask for?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-process-is-painless&quot;&gt;The process is painless&lt;/h2&gt;

&lt;p&gt;Switching from WordPress to Octopress was very easy, and it took me only a few
hours (spread out throughout one weekend). Some highlights:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Comments in Octopress are handled by &lt;a href=&quot;https://disqus.com&quot;&gt;Disqus&lt;/a&gt;, and I had to set that up
on my WordPress blog before transitioning in order to transfer all the
comments.&lt;/li&gt;
  &lt;li&gt;I used the &lt;a href=&quot;https://github.com/benbalter/wordpress-to-jekyll-exporter&quot;&gt;WordPress to Jekyll Exporter&lt;/a&gt; tool to export all my posts
from WordPress to Markdown (with meta-data which Octopress understands). I only
had a bit over 50 posts to worry about, so the process was complete in an
instant.&lt;/li&gt;
  &lt;li&gt;I ran some custom Vim macros to remove and change some excess meta data, as
well as clean up Markdown formatting. I am a perfectionist, and the exporter
tool left me with a poorly formatted document. I couldn’t let that happen.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;results-are-breathtaking&quot;&gt;Results are breathtaking&lt;/h2&gt;

&lt;p&gt;After only a few hours of work, I had a lightning fast, simple, and pragmatic
blog. There is no excess configuration, comments are handled externally, and
the source code for the site and articles is available on GitHub. I am able to
write my posts using Markdown, in my favorite editor, and use git to publish
the resulting articles.&lt;/p&gt;

</description>
        <pubDate>Tue, 22 Jul 2014 07:04:15 +0000</pubDate>
        <link>https://rosipov.com/blog/abandoning-wordpress-for-octopress/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/abandoning-wordpress-for-octopress/</guid>
        
        <category>octopress</category>
        
        <category>wordpress</category>
        
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>Export WordPress posts to plain text</title>
        <description>&lt;p&gt;I prefer to create and edit my posts in plain text. It’s a timeless format, and
I find it nice to have an archive of posts lying around in plain text.&lt;/p&gt;

&lt;p&gt;I wrote a little Python script which I used to extract an archive of my posts
and pages into a bunch of files on my computer. In order to use it, you need to
use “&lt;a href=&quot;http://wordpress.org/plugins/wordpress-importer/&quot;&gt;WordPress Importer&lt;/a&gt;” plugin. Export your posts and pages into a WXR
format, and feed the file to the script.&lt;/p&gt;

&lt;p&gt;Source code of the script is below (link for downloading the script is at the
bottom of this post):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/usr/bin/env python

&quot;&quot;&quot;This script converts WXR file to a number of plain text files.

WXR stands for &quot;WordPress eXtended RSS&quot;, which basically is just a
regular XML file. This script extracts entries from the WXR file into
plain text files. Output format: article name prefixed by date for
posts, article name for pages.

Usage: wxr2txt.py filename [-o output_dir]
&quot;&quot;&quot;

import os
import re
import sys
from xml.etree import ElementTree

NAMESPACES = {
        &apos;content&apos;: &apos;http://purl.org/rss/1.0/modules/content/&apos;,
        &apos;wp&apos;: &apos;http://wordpress.org/export/1.2/&apos;,
}
USAGE_STRING = &quot;Usage: wxr2txt.py filename [-o output_dir]&quot;

def main(argv):
    filename, output_dir = _parse_and_validate_output(argv)
    try:
        data = ElementTree.parse(filename).getroot()
    except ElementTree.ParseError:
        _error(&quot;Invalid input file format. Can not parse the input.&quot;)
    page_counter, post_counter = 0, 0
    for post in data.find(&apos;channel&apos;).findall(&apos;item&apos;):
        post_type = post.find(&apos;wp:post_type&apos;, namespaces=NAMESPACES).text
        if post_type not in (&apos;post&apos;, &apos;page&apos;):
            continue
        content = post.find(&apos;content:encoded&apos;, namespaces=NAMESPACES).text
        date = post.find(&apos;wp:post_date&apos;, namespaces=NAMESPACES).text
        title = post.find(&apos;title&apos;).text
        date = date.split(&apos; &apos;)[0].replace(&apos;-&apos;, &apos;&apos;)
        title = re.sub(r&apos;[_]+&apos;, &apos;_&apos;, re.sub(r&apos;[^a-z0-9+]&apos;, &apos;_&apos;, title.lower()))
        if post_type == &apos;post&apos;:
            post_filename = date + &apos;_&apos; + title + &apos;.txt&apos;
            post_counter += 1
        else:
            post_filename = title + &apos;.txt&apos;
            page_counter += 1
        with open(os.path.join(output_dir, post_filename), &apos;w&apos;) as post_file:
            post_file.write(content.encode(&apos;utf8&apos;))
        post_counter += 1
    print &quot;Saved {} posts and {} pages in directory &apos;{}&apos;.&quot;.format(
            post_counter, page_counter, output_dir)

def _parse_and_validate_output(argv):
    if len(argv) not in (2, 4):
        _error(&quot;Wrong number of arguments.&quot;)
    filename = argv[1]
    if not os.path.isfile(filename):
        _error(&quot;Input file does not exist (or not enough permissions).&quot;)
    output_dir = argv[3] if len(argv) == 4 and argv[2] == &apos;-o&apos; else os.getcwd()
    if not os.path.isdir(output_dir):
        _error(&quot;Output directory does not exist (or not enough permissions).&quot;)
    return filename, output_dir

def _error(text):
    print text
    print USAGE_STRING
    sys.exit(1)

if __name__ == &quot;__main__&quot;:
    main(sys.argv)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can download the script from here: &lt;a href=&quot;https://gist.github.com/ruslanosipov/b748a138389db2cda1e8&quot;&gt;wxr2txt.py&lt;/a&gt;.&lt;/p&gt;

</description>
        <pubDate>Mon, 02 Jun 2014 03:44:12 +0000</pubDate>
        <link>https://rosipov.com/blog/export-wordpress-posts-to-plain-text/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/export-wordpress-posts-to-plain-text/</guid>
        
        <category>python</category>
        
        <category>wordpress</category>
        
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>Python: &quot;ignored&quot; context manager</title>
        <description>&lt;p&gt;There was a recent &lt;a href=&quot;http://hg.python.org/cpython/rev/406b47c64480&quot;&gt;fantastic addition to Python 3.4&lt;/a&gt; by Raymond Hettinger:
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contextlib.ignored&lt;/code&gt;. It’s a context manager which lets you shorten the
following often-occurring pattern:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;try:
    os.remove(&apos;i_probably_do_not_exist.txt&apos;)
except OSError:
    pass
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And turn it into this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;with ignored(OSError):
    os.remove(&apos;i_probably_do_not_exist&apos;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Much shorted and prettier. But, as probably most of engineers, you have to use
older version of python in production. That’s where this little chunk of code
comes in. Create a little &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compat&lt;/code&gt; (as in “compatibility”) library and add
following function:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import contextlib

@contextlib.contextmanager
def ignored(*exceptions):
    try:
        yield
    except exceptions:
        pass
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Beautiful!&lt;/p&gt;

&lt;p&gt;UPDATE: As Andy pointed out in comments, this context manager has been renamed
to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contextlib.suppress&lt;/code&gt; (&lt;a href=&quot;https://bugs.python.org/issue19266&quot;&gt;https://bugs.python.org/issue19266&lt;/a&gt;).&lt;/p&gt;

</description>
        <pubDate>Thu, 29 May 2014 19:20:34 +0000</pubDate>
        <link>https://rosipov.com/blog/python-ignored-context-manager/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/python-ignored-context-manager/</guid>
        
        <category>contextlib</category>
        
        <category>python</category>
        
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>Making Django and Lettuce play nice together</title>
        <description>&lt;p&gt;Lettuce is a great BDD tool which allows you to parse expressions written via
Gherkin syntax in python. However the documentation is not very comprehensive,
and at the moment current version (0.2.19) has some issues integrating with the
latest Django (1.6.1 at the moment of writing). Without further ado, I’ll get
to a comprehensive tutorial.&lt;/p&gt;

&lt;p&gt;Let’s assume you are using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;virtualenv&lt;/code&gt; for the dependency control,
and you already have a working project configured. Your project is called
“myproject”, and the only app you have within your project is called “polls”.&lt;/p&gt;

&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;/h2&gt;

&lt;p&gt;First, you have to install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lettuce&lt;/code&gt; library. At the moment of writing, current
released version (0.2.19) has an error integrating with Django, so we’ll
install current development version. Releases 0.2.20 and up should include the
fix, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip install lettuce&lt;/code&gt; would be better if the version is out.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pip install -e \
    git://github.com/gabrielfalcao/lettuce@cccc397#egg=lettuce-master
pip install django-nose splinter
pip freeze &amp;gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;First line downloads lettuce package from the github repository and installs
missing dependencies. You can replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cccc397&lt;/code&gt; with the current commit.
Technically commit can be omitted, but we don’t want to have an unstable
ever-changing branch in our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requirements.txt&lt;/code&gt;. I also added &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;django-nose&lt;/code&gt;
since nose assertions come in handy while writing Lettuce steps, as well as
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;splinter&lt;/code&gt;, which is a great tool for testing web application.&lt;/p&gt;

&lt;p&gt;Add Lettuce to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INSTALLED_APPS&lt;/code&gt; in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;myproject/settings.py&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;INSTALLED_APPS = (
    &apos;django.contrib.auth&apos;,
    &apos;django.contrib.contenttypes&apos;,
    &apos;django.contrib.sessions&apos;,
    &apos;django.contrib.sites&apos;,
    &apos;django.contrib.messages&apos;,
    &apos;django.contrib.staticfiles&apos;,
    &apos;django.contrib.admin&apos;,
    &apos;django.contrib.admindocs&apos;,
    # ... third party apps ...
    &apos;lettuce.django&apos;,
    &apos;myproject&apos;,
    &apos;polls&apos;,
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You also have to explicitly specify the apps you want to use with lettuce:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;LETTUCE_APPS = (
    &apos;polls&apos;,
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By default, lettuce will run its’ tests against your default database. But we
want to use test database for that, so we have to add few more settings:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;LETTUCE_TEST_SERVER = &apos;lettuce.django.server.DjangoServer&apos;
LETTUCE_SERVER_PORT = 9000
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LETTUCE_TEST_SERVER&lt;/code&gt; is a subclass of Django’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LiveTestServerCase&lt;/code&gt; - a
class which runs a test server for you and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LETTUCE_SERVER_PORT&lt;/code&gt; is different
from port 8000 so you won’t have issues running the development server via
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python manage.py runserver&lt;/code&gt; at the same time as running Lettuce tests.&lt;/p&gt;

&lt;p&gt;You also have to create a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;features&lt;/code&gt; directories inside the apps you want to
test with Lettuce:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/myproject
    /myproject
        __init__.py
        settings.py
        urls.py
        wsgi.py
    /polls
        /features
            /steps
                __init__.py
                polls_list.py
            polls_list.feature
        __init__.py
        models.py
        tests.py
        views.py
    manage.py
    requirements.txt
    terrain.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Lettuce has its’ own settings file called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;terrain.py&lt;/code&gt;. It has to be in the
same directory as a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;manage.py&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;from django.core.management import call_command
from django.conf import settings
from lettuce import before, after, world
from splinter.browser import Browser

@before.each_scenario
def flush_database(scenario):
    call_command(&apos;flush&apos;, interactive=False, verbosity=0)

@before.each_scenario
def prepare_browser(scenario):
    world.browser = Browser()

@after.each_scenario
def destroy_browser(scenario):
    world.browser.quit()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This code flushes the database before each scenario, as well as prepares and
destroys the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;splinter&lt;/code&gt; browser.&lt;/p&gt;

&lt;h2 id=&quot;writing-the-features&quot;&gt;Writing the features&lt;/h2&gt;

&lt;p&gt;Feature files support standard Gherkin syntax, let’s write one right now in
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;polls/features/polls_list.feature&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Feature: Polls list

    Scenario: Polls list without any polls
        When I access the &quot;polls list&quot; url
        Then I see a text &quot;We didn&apos;t find any polls!&quot;

    Scenario: Polls list with one poll
        Given a poll with the title &quot;Hello world&quot;
        When I access the &quot;polls list&quot; url
        Then I see a text &quot;Hello world&quot;
        And I do not see a text &quot;We didn&apos;t find any polls!&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now describe the steps in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;polls/features/steps/polls_list.py&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;from django.core.urlresolvers import reverse
from lettuce import step, world
from lettuce.django import django_url
from nose.tools import assert_in, assert_not_in
from polls.models import Poll

PAGES = {
    &quot;polls list&quot;: &quot;polls:list&quot;
}

@step(r&apos;access the &quot;(.*)&quot; url&apos;)
def access_the_url(step, name):
    world.browser.visit(django_url(reverse(PAGES[name])))

@step(r&apos;see a text &quot;(.*)&quot;&apos;)
def see_a_text(step, text):
    assert_in(text, world.browser.html)

@step(r&apos;a poll with the title &quot;(.*)&quot;&apos;)
def create_a_poll_with_the_title(step, title):
    poll = Poll.objects.create(title=title)
    polls.save()

@step(r&apos;do not see a text &quot;(.*)&quot;&apos;)
def do_not_see_a_text(step, text):
    assert_not_in(text, world.browser.html)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;running-the-tests&quot;&gt;Running the tests&lt;/h2&gt;

&lt;p&gt;Now, you can run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python manage.py harvest --test-server&lt;/code&gt; to run the tests you
just wrote:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ python manage.py harvest --test-server
Creating test database for alias &apos;default&apos;...
Django&apos;s builtin server is running at 0.0.0.0:9000

Feature: Polls list

  Scenario: Polls list without any polls
    When I access the &quot;polls list&quot; url
    Then I see a text &quot;We didn&apos;t find any polls!&quot;

  Scenario: Polls list with one poll
    Given a poll with the title &quot;Hello world&quot;
    When I access the &quot;polls list&quot; url
    Then I see a text &quot;Hello world&quot;
    And I do not see a text &quot;We didn&apos;t find any polls!&quot;

1 feature (1 passed)
2 scenarios (2 passed)
6 steps (6 passed)
Destroying test database for alias &apos;default&apos;...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Don’t forget the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--test-server&lt;/code&gt; switch - otherwise Lettuce will run tests
against your default database.&lt;/p&gt;

&lt;h2 id=&quot;sources&quot;&gt;Sources&lt;/h2&gt;

&lt;p&gt;You can find some more details on Lettuce and Django integration here:
&lt;a href=&quot;http://lettuce.it/recipes/django-lxml.html&quot;&gt;Web development fun with Lettuce and Django&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;update&quot;&gt;Update&lt;/h2&gt;

&lt;p&gt;Rather than using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--test-server&lt;/code&gt; switch, it’s easier and safer to set a flag
in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;settings.py&lt;/code&gt; (suggested by Michel Sabchuk):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;LETTUCE_USE_TEST_DATABASE = True
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This way you won’t end up accidentally erasing your production database after
forgetting to add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--test-server&lt;/code&gt; flag.&lt;/p&gt;

</description>
        <pubDate>Mon, 30 Dec 2013 18:48:31 +0000</pubDate>
        <link>https://rosipov.com/blog/making-django-and-lettuce-play-nice-together/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/making-django-and-lettuce-play-nice-together/</guid>
        
        <category>django</category>
        
        <category>lettuce</category>
        
        <category>python</category>
        
        <category>splinter</category>
        
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>Python doctests and decorators bug</title>
        <description>&lt;p&gt;Now, this as well might be a feature, but doctest strings are not being
executed for decorated functions (at least in version 2.7). However, there is a
workaround.&lt;/p&gt;

&lt;p&gt;You need to decorate your functions with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;functools.wraps&lt;/code&gt; within a decorator
to import docstrings into a decorator scope.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/usr/bin/env python

from functools import wraps

def decorator(func):
    @wraps(func)
    def wrapper():
        return func()
    return wrapper

@decorator
def foo():
    &quot;&quot;&quot;
    &amp;gt;&amp;gt;&amp;gt; foo()
    False
    &quot;&quot;&quot;
    return True

import doctest
doctest.testmod()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now you can see this test failing, where otherwise it would have been ignored:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;**********************************************************************
File &quot;decorator.py&quot;, line 12, in __main__.foo
Failed example:
    foo()
Expected:
    False
Got:
    True
**********************************************************************
1 items had failures:
   1 of   1 in __main__.foo
***Test Failed*** 1 failures.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Mon, 22 Jul 2013 14:57:29 +0000</pubDate>
        <link>https://rosipov.com/blog/python-doctests-and-decorators-bug/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/python-doctests-and-decorators-bug/</guid>
        
        <category>decorator</category>
        
        <category>doctest</category>
        
        <category>python</category>
        
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>Python tests with doctest and unittest</title>
        <description>&lt;p&gt;When it comes to tests, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;doctest&lt;/code&gt; is a great simple module to write tests for
your application. However it is pretty basic and does not have any extended
features like, for example, centralized unit tests. If you have multiple
modules with doctests (and you probably do) you most likely want to be able to
run all doctests recursively from one place. That’s where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unittest&lt;/code&gt; comes in.&lt;/p&gt;

&lt;p&gt;Let’s assume we store modules in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lib/&lt;/code&gt; directory:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ ls lib/
__init__.py bar.py foo.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here are the contents of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo.py&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bar.py&lt;/code&gt; respectfully:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;def foo():
    &quot;&quot;&quot;
    &amp;gt;&amp;gt;&amp;gt; foo()
    False
    &quot;&quot;&quot;
    return False

def bar():
    &quot;&quot;&quot;
    &amp;gt;&amp;gt;&amp;gt; bar()
    True
    &quot;&quot;&quot;
    return True

def baz():
    &quot;&quot;&quot;
    &amp;gt;&amp;gt;&amp;gt; baz()
    False
    &quot;&quot;&quot;
    return False
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, to run all tests we need a wrapper script. Let’s call it: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;runtests.py&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/usr/bin/env python

import unittest
import doctest
import os

files = []
root_dir = &apos;lib/&apos;

for root, _, filenames in os.walk(root_dir):
    for filename in filenames:
        if filename == &apos;__init__.py&apos; or filename[-3:] != &apos;.py&apos;:
            continue
        f = os.path.join(root, filename)
        f = f.replace(&apos;/&apos;, &apos;.&apos;)
        f = f[:-3]
        files.append(f)

suite = unittest.TestSuite()
for module in files:
    suite.addTest(doctest.DocTestSuite(module))
unittest.TextTestRunner(verbosity=1).run(suite)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This approach invokes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;doctest.DocTestSuite&lt;/code&gt; method, which converts
doctests strings into unittest suites. Time to run our tests:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ chmod +x runtests.py
$ ./runtests.py
...
----------------------------------------------------------------------
Ran 3 tests in 0.008s

OK
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And just to be sure that approach actually works, let’s make one of the tests
fail:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ ./runtests.py
.F.
======================================================================
FAIL: baz (lib.bar)
Doctest: lib.bar.baz
----------------------------------------------------------------------
Traceback (most recent call last):
  File &quot;/usr/lib/python2.7/doctest.py&quot;, line 2201, in runTest
    raise self.failureException(self.format_failure(new.getvalue()))
AssertionError: Failed doctest test for lib.bar.baz
  File &quot;/home/rosipov/unitdoc/lib/bar.py&quot;, line 8, in baz

----------------------------------------------------------------------
File &quot;/home/rosipov/unitdoc/lib/bar.py&quot;, line 10, in lib.bar.baz
Failed example:
    baz()
Expected:
    True
Got:
    False

----------------------------------------------------------------------
Ran 3 tests in 0.009s

FAILED (failures=1)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Mon, 22 Jul 2013 14:47:47 +0000</pubDate>
        <link>https://rosipov.com/blog/python-tests-with-doctest-and-unittest/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/python-tests-with-doctest-and-unittest/</guid>
        
        <category>doctest</category>
        
        <category>python</category>
        
        <category>unittest</category>
        
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>pygame.font not found</title>
        <description>&lt;p&gt;I had an issue with pygame not being able to find a dependency for the font
module. After quite a time-consuming search the missing package name was
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libsdl-ttf2.0-dev&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Hope this helps someone.&lt;/p&gt;
</description>
        <pubDate>Thu, 27 Jun 2013 13:51:11 +0000</pubDate>
        <link>https://rosipov.com/blog/pygame-font-not-found/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/pygame-font-not-found/</guid>
        
        <category>pygame</category>
        
        <category>python</category>
        
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>Rails and MongoDB with Cygwin</title>
        <description>&lt;p&gt;Setting up Ruby on Rails with MongoDB on a Windows machine.&lt;/p&gt;

&lt;p&gt;You need to have cygwin installed with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ruby&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt; packages (obviously you
may want to have more).&lt;/p&gt;

&lt;p&gt;The following commands are executed in the cygwin prompt:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone git://github.com/rubygems/rubygems.git
cd rubygems/
ruby setup.rb
gem install rails
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Go to the MongoDB website and download Windows binaries:
&lt;a href=&quot;http://www.mongodb.org/downloads&quot;&gt;http://www.mongodb.org/downloads&lt;/a&gt;. Extract the content of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bin/&lt;/code&gt; directory
to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C:\cygwin\usr\local\bin&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Create a directory for the db files (the default MongoDB db files directory is
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C:\datadb&lt;/code&gt;):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cd /cygdrive/c
mkdir data
mkdir data/db
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Done! Both mongo and rails are in your cygwin’s path now, feel free to tweak it
as you see fit.&lt;/p&gt;
</description>
        <pubDate>Mon, 11 Mar 2013 19:38:30 +0000</pubDate>
        <link>https://rosipov.com/blog/rails-and-mongodb-with-cygwin/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/rails-and-mongodb-with-cygwin/</guid>
        
        <category>mongodb</category>
        
        <category>rails</category>
        
        
        <category>Programming</category>
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>C strtok usage example</title>
        <description>&lt;p&gt;I had some issues with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strtok&lt;/code&gt; function. Here’s a detailed explanation and
usage for it.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strtok&lt;/code&gt; function is used to tokenize a string and thus separates it into
multiple strings divided by a delimiter.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

int main() {
    int j, i = 0;
    char delim[4];
    char user_input[81], *token[80];
    user_input[0] = 0;  // set first byte to 0 to detect empty string

    // validate the string length
    while (strlen(user_input) &amp;lt;= 1 || strlen(user_input) &amp;gt; 82) {
        printf(&quot;Feed me a string to tokenize: &quot;);
        fgets(user_input, sizeof(user_input), stdin);
    }

    printf(&quot;And a delimiter (up to 4 chars): &quot;);
    fgets(delim, sizeof(delim), stdin);

    token[0] = strtok(user_input, delim);  // first call returns pointer
                                           // to first part of user_input
                                           // separated by delim
    while (token[i] != NULL) {
        i++;
        token[i] = strtok(NULL, delim);  // every call with NULL uses
                                         // saved user_input value and
                                         // returns next substring
    }

    for (j=0; j&amp;lt;=i-1; j++) {
        printf(&quot;%sn&quot;, token[j]);
    }

    return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s compile and execute it:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Feed me a string to tokenize: foo/bar/baz
And a delimiter: /
foo
bar
baz
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The first call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strtok&lt;/code&gt; returns the pointer to the first substring. All the
next calls with the first argument being &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NULL&lt;/code&gt; use the string passed at the
first call and return the next substring. The function returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NULL&lt;/code&gt; if no
more substrings are available.&lt;/p&gt;
</description>
        <pubDate>Mon, 10 Dec 2012 18:36:05 +0000</pubDate>
        <link>https://rosipov.com/blog/c-strtok-usage-example/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/c-strtok-usage-example/</guid>
        
        <category>c</category>
        
        
        <category>Programming</category>
        
      </item>
    
      <item>
        <title>Create gitolite repository</title>
        <description>&lt;p&gt;A reminder on how to initialize a fresh gitolite repository, assuming that
gitolite has already been set up.&lt;/p&gt;

&lt;p&gt;All actions are performed on a local machine. In this case: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/gitolite-admin&lt;/code&gt;
is admin repository, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/foo&lt;/code&gt; is desired repository, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rosipov.com&lt;/code&gt; is gitolite
hostname. Command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vi&lt;/code&gt; stands for the text editor, but you may use whichever
editor you prefer.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cd ~/gitolite-admin
vi conf/gitolite.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Add lines (obviously you may want to use individual users instead of @all):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;repo foo
    RW+ = @all
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Save it. Next:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git add conf/gitolite.conf
git commit -m &quot;Add foo repo for @all&quot;
git pull --rebase &amp;amp;amp;&amp;amp;amp; git push
mkdir ~/foo
cd ~/foo
git init
git remote add origin git@rosipov.com:foo.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Add some files at this point. In this example, only &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitkeep&lt;/code&gt; is added.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git add .gitkeep
git commit -m &quot;Initialize repo&quot;
git push origin master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The new repository is all set up now.&lt;/p&gt;
</description>
        <pubDate>Mon, 10 Dec 2012 04:11:23 +0000</pubDate>
        <link>https://rosipov.com/blog/create-gitolite-repository/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/create-gitolite-repository/</guid>
        
        <category>git</category>
        
        <category>gitolite</category>
        
        
        <category>Programming</category>
        
        <category>CLI</category>
        
      </item>
    
      <item>
        <title>C - Reallocating memory for the array</title>
        <description>&lt;p&gt;I just started delving into C and I had some issues with increasing the memory
allocation size for my array. The best way to understand something - write a
detailed explanation of the process. So here we go:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;

// notice that array is a pointer to a pointer
int append_array_element(int **array, int *array_length, int element) {
    *array_length += 1;
    *array = realloc(*array, *array_length * sizeof(int));
    (*array)[*array_length - 1] = element; // [] has higher priority
                                           // then * in C&apos;s order of
    return 0;                              // operations
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We have a pointer to the pointer to the array, pointer to the array’s length,
and a value to append to the array. Array is passed as a pointer to pointer so
we will be able to ‘repoint’ the original pointer to a new memory segment.&lt;/p&gt;

&lt;p&gt;Let’s call the function a few times and see what it gives us.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;int main() {
    int *array = NULL;
    int array_length = 0;

    append_array_element(&amp;amp;array, &amp;amp;array_length, 142);
    printf (&quot;Our array with %d elementsn&quot;, array_length);
    printf(&quot;%dn&quot;, array[0]);

    append_array_element(&amp;amp;array, &amp;amp;array_length, 19);
    printf (&quot;Our array with %d elementsn&quot;, array_length);
    printf(&quot;%dn&quot;, array[0]);
    printf(&quot;%dn&quot;, array[1]);

    return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And the output is:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Our array with 1 elements
142
Our array with 2 elements
142
19
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can never be sure when you work with memory, so let’s add some error
handling in case the operation fails.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;int append_array_element(int **array, int *array_length, int element) {
    *array_length += 1;
    // realloc() returns pointer or False if it fails
    void *_tmp_array = realloc(*array, *array_length * sizeof(int));
    if (!_tmp_array) {
        printf(&quot;Error while trying to realloc memory!n&quot;);
        return -1;
    }
    *array = _tmp_array;
    (*array)[*array_length - 1] = element;

    return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we will be able to handle the crash on our own. But reallocation is not a
very fast thing, so let’s double the amount of reallocated memory every time we
run out of allocated memory. We’ll need one more variable to track the current
allocated memory size.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;int append_array_element(int **array, int *array_length,
                         int *array_alloc_length, int element) {
    *array_length += 1;
    if (*array_length &amp;gt; *array_alloc_length) {
        if (*array_alloc_length == 0) {
            *array_alloc_length = 1;
        } else {
            *array_alloc_length *= 2;
        }

        void *_tmp_array = realloc(*array, *array_alloc_length * sizeof(int));
        if (!_tmp_array) {
            printf(&quot;Error while trying to reallocate memory for an array!n&quot;);
            return -1;
        }
        *array = _tmp_array;
    }
    (*array)[*array_length - 1] = element;

    return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s call it few times:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;int main() {
    int *array = NULL;
    int array_length = 0;
    int array_alloc_length = 0;

    int i;
    for (i = 0; i &amp;lt; 10; i++) {
        append_array_element(&amp;amp;array, &amp;amp;array_length, &amp;amp;array_alloc_length, i);
    }

    printf(&quot;Our array with %d elementsn&quot;, array_length);
    for (i = 0; i &amp;lt; 10; i++) {
        printf(&quot;%dn&quot;, array[i]);
    }
    printf(&quot;Array length: %d, allocated elements: %dn&quot;,
           array_length, array_alloc_length);

    return 0;
}

Our array with 10 elements
0
1
2
3
4
5
6
7
8
9
Array length: 10, allocated elements: 16
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And for the fun of it, let’s do the same with 100 elements:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Our array with 100 elements
0
1
2
...
97
98
99
Array length: 100, allocated elements: 128
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s improve the function a little bit more - and we are good to go. Let’s say
we have a dynamic array with 129 elements - but we will have allocated memory
for 256 elements… It is 127 more then we need! We don’t want to be greedy, so
let’s find a way to free up the memory.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;stdbool.h&amp;gt; // I included this just to use boolean values with
                     // neat true/false aliases

int append_array_element(int **array, int *array_length,
                         int *array_alloc_length, int element,
                         bool is_last_element) {
    *array_length += 1;
    if (*array_length &amp;gt; *array_alloc_length || is_last_element) {
        if (is_last_element) {
            *array_alloc_length = *array_length;
        }
        else if (*array_alloc_length == 0) {
            *array_alloc_length = 1;
        } else {
            *array_alloc_length *= 2;
        }

        void *_tmp_array = realloc(*array, *array_alloc_length * sizeof(int));
        if (!_tmp_array) {
            printf(&quot;Error while trying to reallocate memory for an array!n&quot;);
            return -1;
        }
        *array = _tmp_array;
    }
    (*array)[*array_length - 1] = element;

    return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That should be pretty straight-forward. And let’s call it two more times with
10 and 100 elements:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;int main() {
    int *array = NULL;
    int array_length = 0;
    int array_alloc_length = 0;
    bool is_last_element;

    int i;
    int i_max = 10;
    for (i = 0; i &amp;lt; i_max; i++) {
        if (i == i_max - 1)
        {
            is_last_element = true;
        } else {
            is_last_element = false;
        }
        append_array_element(&amp;amp;array, &amp;amp;array_length, &amp;amp;array_alloc_length,
                             i, is_last_element);
    }

    printf(&quot;Our array with %d elementsn&quot;, array_length);
    for (i = 0; i &amp;lt; i_max; i++) {
        printf(&quot;%dn&quot;, array[i]);
    }
    printf(&quot;Array length: %d, allocated elements: %dn&quot;,
           array_length, array_alloc_length);

    return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And the results are:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Our array with 10 elements
0
1
2
3
4
5
6
7
8
9
Array length: 10, allocated elements: 10

Our array with 100 elements
0
1
2
...
97
98
99
Array length: 100, allocated elements: 100
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Pretty neat, huh? Thank you for reading!&lt;/p&gt;
</description>
        <pubDate>Sun, 02 Sep 2012 01:54:36 +0000</pubDate>
        <link>https://rosipov.com/blog/c-reallocating-memory-for-the-array/</link>
        <guid isPermaLink="true">https://rosipov.com/blog/c-reallocating-memory-for-the-array/</guid>
        
        <category>c</category>
        
        
        <category>Programming</category>
        
      </item>
    
  </channel>
</rss>
