NcduColors is a Python zero-dependency, pre-2.0 Ncdu themes patcher.
Ncdu (NCurses Disk Usage) is a text-user interface disk usage analyzer. It relies on the Ncurses library.
"I really don't see why anyone would spend time theming a disk usage analyzer they (probably) won't use every day, so I'm hesitant to bloat ncdu with even more config options." - Ncdu developer
Software accessibility is a great issue. Ncdu users know it, too.
The 3-bit and 4-bit basic terminal color palette is almost unusable. Every terminal software uses its own palette. No standard seems to be followed at all.
Because of this, the two colorful themes, dark
and darkbg
, are hardly usable for many.
Something is definitely off
Many users (first, second, third, and so on) complained about color issues. I thought it'd be nice to find a solution which could work for the many, not only for me. Also, I use Ncdu a lot, so this definitely was not a waste of time (at the very least, it was a fun learning experience!).
Contributing or forking Ncdu was an option.
However, there are a few issues with this approach:
-
The Ncdu developer said he's quite hesitant to add more themes support to Ncdu.
-
Even if the needed changes were to be made now, many users on LTS distributions couldn't benefit for months or even years. Think of Debian and Ubuntu-based distributions.
-
Forks are harder to compile, to use, to install and to update for regular users. Also let's not fool ourselves, Linux package management is a mess.
-
Forks rely on developers who fork the original project and are more prone to become abandonware due to their nature, rightfully expected to be "secondary" compared to the mainline project.
Instead, NcduColors's approach allows you to change colors now and how you want, while still retaining the possibility to update Ncdu officially, using your package manager, whenever new versions are available (though you will have to re-patch it).
And: you can uninstall NcduColors while preserving your customised Ncdu.
This approach was considered on Ncdu's side, but I think that there will always be someone who doesn't like it. You can't always satisfy everyone when it comes to accessibility issues.
Thus, allowing everybody to painlessy (more or less) patch their own copy of Ncdu seemed the right choice to me.
Also: not everyone loves the black and white (off
) theme.
Install NcduColors from PyPI using Pip:
pip install ncducolors
You have two choices:
-
You can patch a copy of Ncdu (you won't - usually - need root permissions)
- start from step 0
-
You can patch Ncdu in-place (you'll - most likely - need root permissions)
- skip to step 1
You need to copy ncdu
- namely $(command -v ncdu)
- into another $PATH
directory.
A safe choice could be /usr/local/bin
- you can view all of them running tr : '\n' <<< "$PATH"
(beware of the order of priority)
Actually, you can copy Ncdu wherever you want.
A
$PATH
directory is needed just to be able to run Ncdu from anywhere.
From now on, all the steps are in common. Don't forget to specify
--ncdu <PATH_TO_NCDU>
in the arguments.
Run:
ncducolors extract-default-config ncdu-config.json
In case of failure, please open an issue.
It's a good practice to always make backups, even if not strictly needed.
cp ncdu-config.json ncdu-defaults.json
Use your editor of choice to edit the values.
Don't edit the offset
: it could corrupt the binary.
xdg-open ncdu-config.json
Have a look to the table of reference for some help.
Once finished, save and go ahead.
This is the first and only "dangerous" step - well, not really, since you can always fix Ncdu.
Close Ncdu before applying the new configuration, or it won't work.
ncducolors apply-config ncdu-config.json
If you are editing Ncdu in-place, you may need to run NcduColors as root (and, if you installed NcduColors as an unprivileged user, this fixes the "command not found" error).
sudo -E env "PATH=$PATH" ncducolors apply-config ncdu-config.json
That's all. You can now run ncdu
(or ./path/to/your/copy/of/ncdu
).
You can now either:
- Continue to improve your theme jumping back to step 2.
- Revert to your default installation.
- Uninstall NcduColors.
In case something goes wrong, or you just want the plain old Ncdu, don't worry. You can fix it quite easily.
- Try to apply the default config using
ncducolors apply-config ./ncdu-defaults.json
- Try to revert using
ncducolors revert --config ./ncdu-config.json
(the config is needed just to obtain the offset - in fact, you can usencducolors revert --offset N
too) - If you did a backup, use
cp backup-of-ncdu "$(command -v ncdu)"
(you may need to beroot
). - Reinstall Ncdu using your package manager of choice.
key | type | notes |
---|---|---|
ncdu | Path (as string) | Overridden by --ncdu ; autoresolved if null |
offset | Integer | Depends on the binary |
off | Theme | Black and white theme |
dark | Theme | Dark, colorful theme |
darkbg | Theme (if available) | Like dark with forced black background (Ncdu 1.17+) |
key | type | notes |
---|---|---|
default | Key | Used for most of the UI: - file names (unselected) - help pages |
box_title | Key | Used for windows titles: - "ncdu help" - "Item info" - "Confirm delete" |
hd | Key | - Header base text - Footer base text - Help page title (selected) |
sel | Key | File row (selected) |
num | Key | Numbers only, without unit: - file size (unselected) - size in percentage (unselected) - child items count (unselected) - disk usage (Item view) - apparent size (Item view) |
num_hd | Key | Numbers only, without unit (footer) |
num_sel | Key | Numbers only, without unit: - file size (selected) - size in percentage (selected) |
key | Key | Highlighted keys ("Item info", "ncdu help") |
key_hd | Key | - "?" (header) - "1", "2", "3" ("ncdu help"; selected) |
dir | Key | - File name (directories; unselected) - Current directory (under the header) |
dir_sel | Key | File name (directories; selected) |
flag | Key | - File rows's leftmost character (unselected) - Flags ("ncdu help" -> "2:Format") |
flag_sel | Key | File rows's leftmost character (selected) |
graph | Key | Graphical size percentage (unselected) |
graph_sel | Key | Graphical size percentage (selected) |
key | type | notes |
---|---|---|
fg | Color | Foreground color |
bg | Color | Background color |
a | Attribute | Attribute flags |
Standard colors and high intensity colors - have a look here - 3-bit and 4-bit colors are terminal-dependent, thus their usage is discouraged (prefer 8-bit colors, if possible).
name | bit value |
---|---|
Black | 0 |
Red | 1 |
Green | 2 |
Yellow | 3 |
Blue | 4 |
Magenta | 5 |
Cyan | 6 |
White | 7 |
Bright_Black ("Gray") | 8 |
Bright_Red | 9 |
Bright_Green | 10 |
Bright_Yellow | 11 |
Bright_Blue | 12 |
Bright_Magenta | 13 |
Bright_Cyan | 14 |
Bright_White | 15 |
Note: these first 16 colors are aliased to Color0
, Color1
, and so on, until Color15
.
In other words, each of the first 16 colors can be represented in two different ways.
This way, Color0
is Black, Color8
is Bright_Black (or Gray), and so on.
Even 8-bit colors are serialized in the format ColorN
, where N
is any number from 0 to 255.
- Colors 0 to 15 are the 3-bit and 4-bit colors, so nothing new there;
- Colors 16 to 231 are:
- part of a 6 × 6 × 6 RGB cube (216 colors in total);
- mathematical formula:
$${\textbf{N} = 36 \cdot {\color{red}{\textbf{R}}} + 6 \cdot {\color{green}{\textbf{G}}} + {\color{blue}{\textbf{B}}} + 16 \hspace{1em} \text{where} \space 0 \le {\color{red}{\textbf{R}}}, {\color{green}{\textbf{G}}}, {\color{blue}{\textbf{B}}} \le 5}$$ - look to this nice palette for more information and for the lookup-table;
- Colors 232 to 255 are a grayscale from dark gray (
Color232
) to light gray (Color255
) in 24 steps.-
Color232
(Dark gray) is aliased toGray1
, whileColor255
(Light gray) is aliased toGray24
, and so on for the colors in the middle.
-
Seems like there's no simple way to support them (without recreating the entire binary): NcduColors can only allocate 16 bits for the foreground color and 16 bits for the background color.
It's the case of null
value (preferred) or any other unknown color name.
For example, in a white over black terminal, foreground color becomes white and background color becomes black.
name | bit value | notes | does it work? |
---|---|---|---|
Standout | 216 | Best highlighting mode of the terminal | yes |
Underline | 217 | Underlining | yes |
Reverse | 218 | Reverse video | yes |
Blink | 219 | Blinking | yes |
Dim | 220 | Half bright | yes |
Bold | 221 | Extra bright or bold | yes |
Altcharset | 222 | Alternate character set | theoretical support only |
Invisible | 223 | Invisible or blank mode | yes |
Protect | 224 | Protected mode ("selective erase") | theoretical support only |
Horizontal | 225 | theoretical support only | |
Left | 226 | theoretical support only | |
Low | 227 | theoretical support only | |
Right | 228 | theoretical support only | |
Top | 229 | theoretical support only | |
Vertical | 230 | theoretical support only |
Internally, the attributes are expressed as the sum of each single flag, stored in a 4-bit long unsigned integer.
When serialized as a string, the object is expressed as each attribute's name concatenated by the plus ('+') character.
A value of null
resets all attributes.
Note: some texts might appear to be dimmed, but since their attributes are hardencoded elsewhere, they can't be edited via NcduColors.
Remember: not every terminal supports all the available attributes, and sometimes they might deliberately decide to ignore them (e.g.
Blink
), while others may support it but with different behavior.
Check the examples/ subdirectory.
Using the colordiff and xxd packages, you can compare your patched Ncdu binary with the old one.
export NC_LENGTH=360 # or 240, for older versions of Ncdu (pre-1.7)
export NC_THEMES_NUMBER=3 # or 2, for older versions of Ncdu (pre-1.7)
export NC_OFFSET=$(printf '0x%x' 123456) # offset
export NC_BACKUP="/path/to/unpatched/ncdu"
export NC_CURRENT="$(command -v ncdu)"
colordiff -y \
<(xxd -c $NC_THEMES_NUMBER -s $NC_OFFSET -l $NC_LENGTH $NC_BACKUP) \
<(xxd -c $NC_THEMES_NUMBER -s $NC_OFFSET -l $NC_LENGTH $NC_CURRENT)
This will output a 15-rows long hex dump, wide 2 or 3 columns (in groups of 2x4 bytes).
Example - Ncdu 1.15.1 defaults compared to a custom theme
You need to install autoreconf
, autoupdate
and a C compiler to run the tests; gcc
is recommended.
- Add support for Ncdu2 (the newer Zig version).
This means you can use it everywhere, in both private and commercial contexts, for every possible purpose (you can even re-distribute it), as long as you preserve copyright and license notices.