Jekyll2026-03-19T14:20:14+01:00https://layer22.com/feed.xmllayer|twenty|twoFunctional Web ApplicationsPiotr Usewicz[email protected]Swift and Cute Framework: Setting up a project with CMake2025-06-06T09:26:00+02:002026-03-19T14:19:30+01:00https://layer22.com/swift-and-cute-framework-setting-up-a-project-with-cmakeCute Framework is a simple, yet powerful C/C++ framework for building 2D games using the modern GPU pipeline. While C or C++ is fine, Swift is a modern language that many developers prefer for its safety and expressiveness. In this post, we will explore how to set up a project using Cute Framework with CMake, enabling you to write your game logic in Swift while leveraging the performance of C/C++ for rendering and other performance-critical tasks.

Prerequisites

Before we begin, ensure you have the following installed:

  • Swift (latest version, preferably Swift 6 or later)
  • CMake (we are going to use the most recent version 4.0, but 3.20+ should work just fine)
  • Ninja (required for building Swift with CMake)

Setting Up the Project Structure

Create a new directory for your project and navigate into it:

mkdir MyCuteGame
cd MyCuteGame

Create the following directory structure:

mkdir src include
touch CMakeLists.txt # Our CMake configuration file
touch src/main.swift # Our main Swift file
touch include/shim.h # Our C header file for Swift interoperability
touch include/module.modulemap # Our C module map for Swift interoperability

The next step is to configure the CMakeLists.txt file. Open it in your favorite text editor and add the following content:

cmake_minimum_required(VERSION 4.0)

# Set the project name and languages
project(
    MyCuteGame
    LANGUAGES C CXX Swift # Ensure we include C, C++, and Swift
)

# Set our game sources
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS src/*.swift)

# Set our executable target
add_executable(MyCuteGame ${SOURCES})

# Include FetchContent to download Cute Framework
include(FetchContent)

# Define cute as our Cute Framework dependency
FetchContent_Declare(
    cute
    GIT_REPOSITORY https://github.com/RandyGaul/cute_framework
)
# Fetch the Cute Framework
FetchContent_MakeAvailable(cute)

# Add the Cute Framework as a dependency
target_include_directories(MyCuteGame PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
target_link_libraries(MyCuteGame cute)

The CMakeLists.txt file defines few key components:

  • It sets the project name and specifies that we will be using C, C++, and Swift. We use C and C++ as Cute Framework is written in C/C++.
  • It collects all Swift source files in the src directory.
  • It sets up the Cute Framework as a dependency using FetchContent, which allows us to download and include it directly in our project.
  • It creates an executable target named MyCuteGame and links it with the Cute Framework.
  • It includes the include directory for header files, which will be used for Swift interoperability.

Setting Up Swift Interoperability

To enable Swift to call C functions, we need to create a C header file and a module map. Open include/shim.h and add the following content:

#pragma once
#include <cute.h>

The shim.h file includes the Cute Framework header, allowing Swift to access its functions.

Next, create the module map in include/module.modulemap:

module CCute [extern_c] {
    header "shim.h"
    export *
}

This module map tells Swift how to import the C header file. The extern_c attribute indicates that this module is a C module, which is necessary for Swift interoperability.

With all that in place, we can now write our Swift code in src/main.swift. Open this file and add the following content:

import CCute

// Center the window on the screen
let options: CF_AppOptionFlags = Int32(CF_APP_OPTIONS_WINDOW_POS_CENTERED_BIT.rawValue)
let width: Int32 = 800
let height: Int32 = 600

// Create the Cute Framework app
let result = cf_make_app("MyCuteGame", 0, 0, 0, width, height, options, CommandLine.unsafeArgv[0])
if cf_is_error(result) {
  fatalError("Failed to create Cute Framework app")
}

// Create a demo girl sprite
var sprite = cf_make_demo_sprite()
// Play the "spin" animation
cf_sprite_play(&sprite, "spin")
// Make the sprite 4x larger
sprite.scale = CF_V2(x: 4.0, y: 4.0)

while cf_app_is_running() {
  // Update internal app state without a callback
  cf_app_update(nil)

  // Update the sprite state
  cf_sprite_update(&sprite)

  // Draw the sprite
  cf_sprite_draw(&sprite)

  // Draw the app onto the screen with clearing enabled
  cf_app_draw_onto_screen(true)
}

cf_destroy_app()

Configure and Build the Project

Now that we have our project structure and code set up, we can configure and build the project using CMake. Open a terminal in the root directory of your project and run the following commands:

mkdir build       # Create a build directory
cd build
cmake -G Ninja .. # Configure the project using CMake with Ninja as the generator
cmake --build .   # Build the project

All that’s left is to run the executable. You can do this by executing:

./MyCuteGame

This should launch your Cute Framework application, displaying a window with a spinning girl sprite.

MyCuteGame

Et voilà! You have successfully set up a Cute Framework project using CMake and Swift. You can now start building your game logic in Swift while leveraging the performance of C/C++ for rendering and other tasks.

I encourage you to explore the documentation, and especially the Getting Started guide.

There is also a Discord server where you can ask questions and share your projects: Cute Framework Discord.

]]>
Piotr Usewicz[email protected]
Configure MacVim to Automatically Switch Colorschemes Based on macOS Dark or Light Theme2023-08-23T15:08:00+02:002026-03-19T14:19:30+01:00https://layer22.com/configure-macvim-to-automatically-switch-colorschemes-based-on-macos-dark-or-light-themeIntroduction

MacVim is a powerful text editor that can be customized to suit your preferences. One of the ways to enhance your MacVim experience is by configuring it to change its colorscheme based on the macOS dark or light theme. In this blog post, I will guide you through the process of setting up MacVim to automatically switch colorschemes depending on your macOS theme.

Code for your .vimrc:

let g:light_theme = 'dayfox'
let g:dark_theme = 'nightfox'

func! s:ChangeBackground()
    let s:theme = g:light_theme

    if (v:os_appearance)
        let s:theme = g:dark_theme
        set background=dark
    else
        set background=light
    endif

    execute 'colorscheme ' . s:theme

    " Ensure we re-init lightline
    let g:lightline.colorscheme = s:theme
    call lightline#init()
    call lightline#colorscheme()
    call lightline#update()

    redraw!
endfunc

call s:ChangeBackground()

augroup AutoDark
autocmd!
autocmd OSAppearanceChanged \* call s:ChangeBackground()
augroup END

What does it all do?

First, define the light and dark colorschemes you wish to use. In the example code, I’m using ‘dayfox’ for the light theme and ‘nightfox’ for the dark theme. You can replace these with any other colorschemes you prefer.

let g:light_theme = 'dayfox'
let g:dark_theme = 'nightfox'

Next, create a function called s:ChangeBackground() to handle the colorscheme change based on the macOS theme setting. This function will:

  • Set the default colorscheme to the light theme.
  • Check the value of v:os_appearance. If it’s true (1), macOS is set to dark mode, and the dark theme will be used. Otherwise, the light theme will be used.
  • Apply the chosen colorscheme and update the lightline colorscheme accordingly.
  • Call the necessary lightline functions to initialize, set the colorscheme, and update the status line.
func! s:ChangeBackground()
    let s:theme = g:light_theme

    if (v:os_appearance)
        let s:theme = g:dark_theme
        set background=dark
    else
        set background=light
    endif

    execute 'colorscheme ' . s:theme

    " Ensure we re-init lightline
    let g:lightline.colorscheme = s:theme
    call lightline#init()
    call lightline#colorscheme()
    call lightline#update()

    redraw!
endfunc

Call the s:ChangeBackground() function to set the initial colorscheme based on the current macOS theme.

call s:ChangeBackground()

Finally, create an autocommand group called AutoDark that will listen for the OSAppearanceChanged event. When the event is triggered, the s:ChangeBackground() function will be called, and the colorscheme will be updated accordingly.

augroup AutoDark
autocmd!
autocmd OSAppearanceChanged * call s:ChangeBackground()
augroup END

Conclusion

By following these steps and using the provided example code, you can configure MacVim to automatically switch between light and dark colorschemes based on the macOS theme.

]]>
Piotr Usewicz[email protected]
My Journey From QWERTY to Norman and Back: A Vim User’s Tale2023-04-09T04:38:00+02:002026-03-19T14:19:30+01:00https://layer22.com/my-journey-from-qwerty-to-norman-and-back-a-vim-users-taleAs a programmer and avid typist, I’m constantly on the lookout for ways to improve my typing experience. In my quest for a more efficient keyboard layout, I decided to embark on a journey to switch from the traditional QWERTY layout to the Norman layout, only to find myself back at QWERTY due to some unforeseen difficulties with Vim. In this blog post, I’ll share my experiences, the pros and cons of each layout, and what I learned along the way.

Introduction

For many, many years, I have been intrigued by alternative keyboard layouts. I always wondered whether they brought value to day-to-day work as a software engineer. Quite early in my career, I bumped into people using Dvorak and Colemak. I wanted to find out for myself, but the idea of learning, and thus struggling to type quickly for some time, would always put me off, so I kept postponing the decision to switch.

Things changed drastically when I decided to change my standard keyboard to the more ergonomic ErgoDox EZ and eventually the Moonlander with sculpted blank keycaps. Given the slight difference in keyboard layout, such as the ortho-linear key layout, the thumb cluster, the default position of the Command, Backspace or Delete keys meant that there was a time in which my typing speed was impacted negatively.

I challenged myself to keep practising daily on websites such as ZSA’s own Train, Monkeytype or Keybr. After a good month or two, I was back at ~80 words per minute. Life was glorious again!

The whole process made me realise that however painful the initial period was, I was able to overcome it and eventually become as productive as before. It also felt satisfying to combat old habits.

The Allure of the Norman Layout

The QWERTY keyboard layout, created in the late 19th century, is widely used today despite its somewhat inefficient design. In search of a better alternative, I came across the Norman layout, created by David Norman in 2012. The layout claims to offer a more efficient typing experience by placing the most frequently used keys on the home row and minimizing finger movement.

I picked this particular layout because it’s not too far off from QWERTY while still bringing the benefits of an optimised typing experience on the home row. Maintaining the Cmd+Z,X,C,V key combinations was particularly important, as I felt hunting for those during the learning period would be just a bit too much. Plus Aaron Patterson uses it, so it must be good, right?!

The Transition

Going with Norman, as a Vim user, I knew that the standard normal mode navigation keys would be in entirely different positions. This was far from perfect, but it encouraged me to continue learning.

Fast-forward 2-3 months, it finally felt natural typing prose using Norman. I enjoyed how balanced typing felt and how little my fingers had to move away from the home row to type many words. Looking at the statistics, my typing speed has not improved. It did feel more effortless, though.

The Vim Dilemma

As a programmer, I rely heavily on the Vim text editor for coding and editing text. Vim is known for its powerful and efficient keyboard-driven interface, which allows users to navigate and manipulate text quickly without using a mouse. However, Vim’s keybindings are designed with the QWERTY layout in mind. When I switched to the Norman layout, I quickly realized that many of Vim’s most essential commands were no longer easily accessible.

The habit of navigating Vim using the hjkl keys on a standard QWERTY keyboard is inherently tied to the whole editing experience. While I was able to navigate when using Norman, it would never feel as natural as on QWERTY. This bugged me a lot.

Things got even more annoying when I had to detach my MacBook from the external keyboard and use it on the go. I would typically use QWERTY in this configuration and noticed that I could not touch-type any more. I had to stare at the keyboard to fish some of the keys. I was stuck with this scenario for a few months, as I wanted to see if things would improve.

Unfortunately, they did not. I missed the natural navigation in Vim. Some people suggested remapping the navigation keys to bring them back to the home row, but that idea did not feel attractive to me, given the occasional switch to QWERTY.

It became increasingly evident that the Norman layout was not a viable option for my workflow as a Vim user. With a heavy heart, I decided to switch back to the QWERTY layout.

Returning to QWERTY

Switching back to QWERTY was a surprisingly smooth process. My muscle memory from years of using the QWERTY layout quickly returned, and I was back to my normal typing speed within a few days. While I missed the ergonomic benefits of the Norman layout, I was relieved to have the full power of Vim at my fingertips again.

Lessons Learned

My journey from QWERTY to Norman and back taught me a few valuable lessons:

  • Experimentation is essential: Trying out different keyboard layouts can lead to a more comfortable and efficient typing experience. It’s crucial to explore and find what works best for you and your specific needs.

  • Compatibility matters: While a keyboard layout may offer ergonomic benefits, it’s essential to consider compatibility with the tools and software you use daily.

  • Adaptability is key: As a typist, being adaptable and willing to learn new layouts can open up new possibilities and improve your overall typing experience.

Conclusion

Although my journey from QWERTY to Norman and back didn’t end in a permanent switch, it was an enlightening experience. I have a newfound appreciation for the importance of keyboard layouts and their impact on my daily life as a programmer. While the Norman layout wasn’t the right fit for my Vim-centric workflow, it may be the perfect solution for someone else. Don’t be afraid to experiment and find the layout that works best for you.

]]>
Piotr Usewicz[email protected]
Fish Shell abbreviations–what are they and how to configure them?2022-12-16T05:27:00+01:002026-03-19T14:19:30+01:00https://layer22.com/fish-abbreviationsFish Shell abbreviations are a fantastic way to configure what is commonly known as aliases for your day-to-day use.

The difference between an alias and an abbreviation is that it expands to the entire command whenever the abbreviation gets triggered. Traditionally, aliases are shown as they are typed in the shell’s history.

The expansion is an excellent benefit of using abbreviations. One can always see the actual command behind the shorthand version. This is both useful for remembering the actual command and significant when sharing commands with others (such as in screenshots of the terminal), as they do not have to decode the aliases.

Let’s configure some abbreviations

We will edit the ~/.config/fish/conf.d/abbreviations.fish file. Any file in the ~/.config/fish/conf.d directory will be automatically loaded in a standard fish setup. A separate file for abbreviations makes it easier to find the right place to configure them.

Below is the content of my file:

abbr be "bundle exec"

abbr ghb "gh browse" # Open the current repository on GitHub
abbr ghc "hub compare" # Open the diff of the branch on GitHub

abbr bu "brew upgrade"

As you can see, the syntax is similar to the alias. We use the abbr command, followed by the abbreviation we’d like to use. Finally, the actual command it should expand to.

To use the configured abbreviation, we need to type it, and either press Enter to expand and execute, or Space to only expand it, allowing us to add any arguments to the command.

Here’s a demo:

asciicast

Abbreviations add another touch of clarity to your own workflow. Switching from using aliases is trivial. To me, they are superior and a clear improvement.

Bonus points

I’ve found fish-git-abbr plugin to be a fantastic collection of predefined abbreviations for git usage. It’s got everything you might need when working with git and save some keystrokes. I have also learned some new git arguments!

]]>
Piotr Usewicz[email protected]
Keep your Heroku Ruby version and .ruby-version synchronised2015-12-19T11:32:00+01:002026-03-19T14:19:30+01:00https://layer22.com/keep-your-heroku-ruby-version-and-ruby-version-synchronisedNot everybody realizes that the Gemfile is just another Ruby script that can contain arbitrary Ruby code. Sure, it does understand some DSL such as gem, ruby or source but we can use it to make our lives a bit easier if we use Heroku to deploy our app and rbenv or rvm to manage Ruby version locally.

This trick I use for my Heroku applications allows me to upgrade the Ruby version used quickly. Especially useful for doing any security-related upgrades, such as the latest Ruby 2.2.4 security release that fixes CVE-2015-7551.

Typically, your Gemfile looks like below:

source 'https://rubygems.org'

ruby '2.2.4'

gem 'rails'

And your .ruby-version contains:

2.2.4

To have our Gemfile use the .ruby-version content to let Heroku know which version of Ruby to use, we need to read the .ruby-version file in the Gemfile as follows.

ruby File.read('.ruby-version').chomp

The code above instructs the Gemfile to read the Ruby version from the .ruby-version file, making it one step less to change your Ruby version, as you don’t have to update two files anymore.

The extra chomp at the end eliminates the new-line character at the end of the number that will exist when reading the .ruby-version file.

]]>
Piotr Usewicz[email protected]
TIL: Use Rails travel functions instead of timecop or time-warp2015-03-09T11:21:00+01:002026-03-19T14:19:30+01:00https://layer22.com/til-use-rails-travel-functions-instead-of-timecop-or-time-warpIf you were using timecop or time-warp gems like me before, you will be happy to hear that Ruby on Rails provides its own travel and travel_to methods that allow you move in time and test time sensitive methods.

It’s great to see that you don’t need an external gem for this!

test 'creates a post in the past' do
  travel_to(5.days.ago) do
    @post = Post.create
  end
  assert_equal 5.days.ago, @post.created_at
end

Read more at OmniRef.

]]>
Piotr Usewicz[email protected]
Standardising coding style across the team with RuboCop2015-02-24T22:45:00+01:002026-03-19T14:19:30+01:00https://layer22.com/standardising-coding-style-across-the-team-with-rubocopAs some of you realise, there are times when you open an old file containing code and you think “WTF”. It’s also very likely that it is a file that you have created months or even years ago, and completely forgot about it.

Some of the issues with code and people are that people have opinions. Some are more vocal than others, some are more passionate; some are plain silly. And it can be a pain, when you for the Nth time have a discussion about indentation, length of methods, naming conventions, hashrockets vs. new Ruby hash syntax, and all those silly things that really make no difference, but make people release their Krakens.

So I have an idea on how to improve the Standard™. RuboCop is a great piece of software that can unobtrusively let you know about style problems within your code. It’s fully configurable and comes with a vast collection of rules that one can enable and configure. You want hashrockets everywhere? No problem! You want new lines at the end of the file? Sure! Methods under 10 lines? Fuck yeah!

Now, I do realise that some of the rules within the Ruby Styleguide are not fantastic, but I do believe that it’s a great way to start unifying your team’s codebase. It will make your lives easier, and writing code will be that much faster. The expectations when opening a file with code will be the same.

This is how RuboCop can work with your Vim:

RuboCop in VIM with Syntastic

It comes with plugins for Sublime Text, TextMate, Atom, what have you. There is also a hosted service at HoundCI that checks your pull requests and posts comments about style improvements.

What’s also great, that RuboCop has a built-in code upgrade tool. It will go through all your code and magically translate it to the style of our choosing. I’ve tried it, even on a big project and it works.

All it takes is just drop one rubocop.yml file in our project and install the editor plugin or HoundCI.

]]>
Piotr Usewicz[email protected]
How to create a website spider2015-01-28T00:51:00+01:002026-03-19T14:19:30+01:00https://layer22.com/how-to-create-a-website-spiderCreating a spider that generates a list of URLs for a given domain is very easy to do.

Spider simply visits each page in a domain, finds all the links and visits those.

With help from a gem called Spidr we can achieve that with few lines of code.

require 'spidr'
urls = []

Spidr.site('http://www.layer22.com/') do |spider|
  spider.every_url do |url|
    urls << url
  end
end

Fetching page content is also easy:

require 'spidr'
contents = []

Spidr.site('http://www.layer22.com/') do |spider|
  spider.every_page do |page|
    contents << page.body
  end
end

What if we are only interested in paragraphs?

require 'spidr'
paragraphs = []

Spidr.site('http://www.layer22.com/') do |spider|
  spider.every_page do |page|
    next unless page.content_type =~ %r(text/html)
    paragraphs << page.doc.search('p').map(&:text)
  end
end
]]>
Piotr Usewicz[email protected]
Spring-load your Rails development environment to speed it up2013-12-05T12:15:00+01:002026-03-19T14:19:30+01:00https://layer22.com/spring-load-your-rails-development-environment-to-speed-it-upThere is a wide selection of tools that allow you to pre-load your Rails development environment to make it faster. We have Zeus, Spork or Spin.

All of them are great and help you work with your development environment faster, but there is a new contestant—Spring by Jon Leighton.

What sets it apart from others is fantastic integration with Rails—in fact, it will be a default with all new Rails 4.1 applications.

So what does it give us?

It pre-loads your development environment in the background without all the hassle of starting up servers etc.

All you need to do is simply add it to your project, install the gem and off you go:

In your Gemfile:

group :development do
  gem 'spring'
  gem 'spring-commands-rspec'
end

The second gem also adds support for rspec binstub, so running your tests will use the preloaded environment.

We need to install the gem locally, so we don’t need to load it via bundle exec (which is slow!).

gem install spring
gem pristine --all
spring binstub --all

Let’s compare time differences for rake routes:

Without Spring:

$ time rake routes

  4.32 real 0.10 user 0.06 sys

Now with Spring:

$ time bin/rake routes

  0.89 real 0.12 user 0.07 sys

Notice that we are using the generated binstub. You can achieve the same result by using spring rake routes.

There are other commands and configuration options that allow you to fine-tune your environment. It’s all available in the README.

Enjoy your faster running development environment.

]]>
Piotr Usewicz[email protected]
Automatically bundle controller-specific assets2013-11-24T22:32:00+01:002026-03-19T14:19:30+01:00https://layer22.com/automatically-bundling-controller-specific-assetsIt’s very convenient to be able to automatically bundle some of the assets in a separate file eg. when you have a lot of controller/resource specific CSS or JavaScript.

Let’s say we are writing a blog, and we have two controllers—one for posts and one for comments. We would also like to separate the stylesheets for them, because, well, they are huge and only apply to either posts or comments.

All we have to do is add rails-controller-assets gem. It will look for assets that match either {controller_name}.css or {controller_name}_{action_name}.css.

In your Gemfile simply add:

gem 'rails-controller-assets'

Now let’s add a new bundle file for both posts and comments:

In app/assets/stylesheets/posts.css:

.post-title { color: blue }

In app/assets/stylesheets/comments.css:

.comment-title { color: brown }

The last step is to let the stylesheets_link_tag know what other files to include:

In yout app/views/layouts/application.html.erb:

<%= stylesheets_link_tag 'application', *controller_stylesheets %>

This will make sure that the current action, when rendered will have all the defined bundles included.

The same can be applied to JavaScript with:

<%= javascript_include_tag 'application', *controller_javascripts %>

Bundle files follow the same pattern: {controller_name}.js or {controller_name}_{action_name}.js.

From now on, each page will be served with it’s own bundle file which will give us faster download speeds and rendering in browser.

The same pattern can be applied manually by adding config.assets.precompile += %w(posts.css comments.css) in your application.rb file, but this gem does it automatically, so you will never forget to add your file there.

]]>
Piotr Usewicz[email protected]