“Hi, my name is Alessandro, and… I use nano.”
There. I said it. After years of quietly pressing
Ctrl+X
, answering “Yes” to save, and living in fear of the
VIM and EMACS inquisitors, I’ve finally come out. While
the big kids fight eternal holy wars over modal editing and Lisp
extensibility, some of us took the small editor from GNU and just… got
work done. Don’t judge.
But even within our tiny community of nano
users, we are
not free of pain. Our cross to bear is called…
tabs.
The mystery: why my tabs turned into spaces
The story begins innocently: I opened a file in nano
,
full of perfectly fine tab characters. But then, the moment I dared to
use my mouse to copy some text from the terminal window… BAM! My tabs
were gone. Replaced by spaces.
It didn’t matter if I used KDE Konsole or GNOME Terminal, the effect was the same: mouse copy -> spaces. I was betrayed.
Meanwhile, if I ran cat file.txt
and selected text with
the mouse, the tabs survived. It was as if the gods of whitespace
personally mocked me.
First hypothesis:
nano
must be guilty!
Naturally, my first instinct was to point fingers at
nano
itself. After all, nano
has options like
tabsize
and tabstospaces
. Maybe
nano
secretly converts tabs into spaces when rendering
text? Maybe I’d been living a lie, editing “tabs” that were never really
tabs?
I started investigating, even hex-dumping what nano sends to the
terminal. Made a file containing only a tab and a blank. What I found
was not 09
(tab) bytes at all, but ANSI escape sequences
like:
That, dear reader, is ncurses
at work.
The real culprit: ncurses, the decorator
Nano is innocent, it loves tabs just as much as I do. The real
problem is ncurses, the library nano
uses to paint text
on the screen.
ncurses
doesn’t just pass \t
straight to
the terminal. Instead, it calculates how many spaces are needed to reach
the next tab stop and paints that many literal spaces, usually
wrapped in shiny SGR sequences (color codes).
So when your terminal emulator builds its screen buffer, all it sees are decorated blanks. And when you drag your mouse to copy… guess what you get? Spaces. Always spaces.
Meanwhile, cat
writes literal \t
to the
terminal, and some emulators (notably VTE-based ones like GNOME Terminal
used to, though mileage varies) preserve that information for mouse
copy. That’s why cat
behaves “correctly” and
nano
doesn’t.
So yes: the real villain in this love story is not nano
,
but ncurses
… The overzealous decorator.
Escape plan: bypass the screen, go straight to clipboard
If the terminal screen can’t be trusted, we need another path. Enter: OSC 52.
OSC 52 is an ANSI escape sequence that lets a program say:
“Hey terminal, please put this base64-encoded text directly into the system clipboard.”
Example:
Paste somewhere else -> boom, you get
Hello<TAB>World
.
This bypasses ncurses
, bypasses the screen, bypasses
mouse selection entirely. The text, tabs and all, travels straight into
your clipboard.
Limitations: it’s not all sunshine and rainbows
- Terminal support: Only terminals that implement OSC
52 can do this. xterm, iTerm2,
Alacritty, recent Konsole are good.
VTE-based terminals (
GNOME Terminal
,Tilix
, etc.)… nope, they deliberately don’t support OSC 52 (for “security reasons”). - Buffer size: Many implementations cap OSC 52 payloads at ~100 KB. Big selections won’t copy entirely.
- Security paranoia: Some distros disable it, since malicious programs could silently overwrite your clipboard. (But honestly, what’s worse: malware, or spaces where you wanted tabs?)
My dream:
nano
with native OSC 52 support
Right now, the only workarounds are… well, kind of clumsy:
- Write the buffer (or a marked region) out to a pipe using
^O | osc52-copy
. - Or just step outside
nano
entirely and runcat file | osc52-copy
.
But there’s no way in nano
today to say “when I press
^K
, also shove this into the clipboard”. nano
simply doesn’t have a hook for that.
That’s why my dream is to add a proper set osc52
option.
With it enabled, nano
would take whatever you cut (or
marked) and send it straight to the terminal clipboard using OSC 52.
Ideally, it would be optional, nobody wants to suddenly discover
nano
has hijacked their clipboard without asking, or just
play with the multitude of clipboard Linux users has: system, primary,
application…
Epilogue
So here I stand, a proud but slightly broken nano
user,
with tabs that keep turning into spaces when I least expect it. I’ve
learned the truth: it’s not nano
’s fault, but
ncurses
. I’ve found salvation in OSC 52, though only if my
terminal plays along.
And who knows, maybe one day there’ll be a tiny patch upstream, and
nano
will finally get to shout “COPY WITH TABS!” directly
into our clipboards. Until then… I’ll try to refine my proposal to make
this ocs52 goal near.
It still lacks the feature to make it optional, but for the time being it demonstrate at least a possible approach.
Stay tuned
UPDATE1: On Sep 1, 2025, I sent a regular patch to the nano
maintainers; let's see what happens.
UPDATE2: After I sent the patch, Benno (nano
’s maintainer) gently reminded me that I hadn’t done my homework well. Turns out I wrongly accused poor ncurses
of tab treachery, but the real culprit is none other than nano
itself. Yes, my beloved editor is the true tab betrayer! (See src/winioc.c:1872). Still, love is blind: I don’t care, I’m sticking with nano
. At the end of the day nano
or ncurses
, it doesn't really matters: if you try to select and take the text on nano
, you won't have your tabs, so I still have reasons for submiting. And since my patch hasn’t been rejected yet, there's still chances the OCS52 can hit nano
’s codebase.