How can I put an nonprintable character in a nix expression?

I would like to build a config file with a nonprintable character in it (because reasons)

I’d rather not have a bunch of characters scattered about my config which I can’t distinguish, so I put them in an attribute set so that I can handle them by reference, then I use pkgs.substituteAll to insert them into the file.

unicode-values.nix

{
  #e107 = "\uE107";  # doesn't work
  e107 = ""; # works
}

zellij-config.nix

{ pkgs, ... }:
let
  unicodeValues = import ./unicode-values.nix;
  zellijConfig = pkgs.substituteAll {
    src = ./config/zellij/config.kdl;
    e107 = unicodeValues.e107;
  };

in {
  home.file."zellij-config" = {
    source = zellijConfig;
    target = ".config/zellij/config.kdl";
  };
}

config/zellij/config.kdl

        bind "@e107@" { SwitchToMode "Normal"; }

~/.config/zellij/config.kdl

        bind "" { SwitchToMode "Normal"; }

… so that works just fine. But what I’d really like is to not have unprintable characters in my nix code at all. When I try “\uE107” instead of “”, the target file ends up with uE107 instead of the desired unicode.

~/.config/zellij/config.kdl

        bind "uE107" { SwitchToMode "Normal"; }

Is there a way to do use escape codes to reference these characters so that I don’t have to copy and paste them into my nix code?

1 Like

Not a direct answer to your question, but an alternative is to use one of the F keys not present on your keyboard(f12+) and use something like xremap to remap a key combo to it. I am using capslock to emit Esc when tapped and f19 when held down with one of the letters to perform shortcuts in window manager. Similar approach could probably be used for zellij.

There is not [edit: in Nix string literals]. Not only is Nix completely Unicode-unaware (strings are just good old null-terminated byte arrays), it doesn’t even have hex escapes for bytes.

Edit: @mwhite is cleverer than I am!

I do like that approach in general, thanks for pointing it out.

In this case I’m being a bit silly and trying to make it work “my” way just to see if I can bend the machine to my will.

Thanks very much, that answers it.

I probably won’t do this, but just to scratch the curiosity itch… I could presumably write a function which would consume strings like “\uE107” and provide the unicode character I seek, yeah?

You probably could! You’d need something like a table of all the non-zero bytes as strings, since I don’t think there’s any built-in int-to-character function, and the table that ships with Nixpkgs only covers ASCII characters. But that, some light parsing logic, and an implementation of UTF-8 encoding should all be possible.

1 Like

It looks like you can use JSON escape sequences along with builtins.fromJSON. For example, if I use nix repl to evaluate builtins.fromJSON '' "\ue107" '', I see "" printed as the result. (Note that I’m using nix version 2.18.1).

2 Likes