I'm a long-time user of i3 (now sway). I wrote this tool to provide the elegance of i3 to terminal users everywhere, especially for people like myself who sometimes use a non-i3 wm or no window manager at all (e.g. when testing code on a bare-bones raspberry pi).
In my experiments for a good multiplexer to go with nnn https://github.com/jarun/nnn, I have tried dvtm and tmux. dvtm is extremely light but it appears there's no way to open a new command in a new pane from within a session. This is where tmux trumped.
So if I want to open 2 panes, I run
dvtm n n # n is aliased to nnn + some program options
But if I want to open text/image files detached in a new pane, my custom opener calls:
tmux split-window -h "vim \"$*\""
Can 3mux do both for me?
- present a lightweight multiplexer
- support options to open split windows and run a command
Note: This is not necessarily i3-specific, please consider cross-DE/WM scenarios.
Looks awesome, thanks for sharing! I've been using Byoyu[0] which has a similar goal, but I'm keen on trying out. Even though I've been a long-time tmux user, as a developer I don't even know where I would start if I wanted to build my own terminal multiplexer. Can you share some resources etc on what could a good starting point if I want to explore this as a side-project?
My understanding is that a terminal multiplexer consists of three parts:
1. Managing shells and windows
2. Parsing the ECMA-35/ECMA-48 escape/control sequences
3. Rendering the shells' parsed output within their window boundaries
> Can you share some resources etc on what could a good starting point if I want to explore this as a side-project?
I have a somewhat different, layered, architecture with finer grained components. The terminal emulators, multiplexor, input method handler, and realizers are all separate processes, and the communication among them is via (memory-mapped) regular files and FIFOs.
It's more rigid in the multiplexing layer, with little notion of creating and destroying inner terminals on the fly and no notion of windows or panes, because it was initially created to be a user-space workalike for the kernel virtual terminals in Linux and FreeBSD, that are derived from SCO Multiscreen. So there's just the notion of a fixed set of virtual terminals, presented one at a time, with the Alt+function-key switching and a replacement chvt command.
It's more flexible in other ways, though. The components of the system are replaceable, and don't have to be put together in this particular way. There's no reason that one couldn't write another type of emulator, handling a completely different suite of escape and control sequences, and just plug it in alongside the existing one. And there's similar flexibility in the other layers: one can (and I do) simultaneously realize the same set of multiplexed terminals onto a remote terminal over an SSH connection as well as directly onto the local machine's framebuffer and keyboard(s). It could be realized onto X11, or (if someone finally documents the undocumented Mosh protocol) a Mosh client.
Indeed, there's no reason that a more complex multiplexing layer couldn't be substituted, providing something more like the screen/tmux paradigm, with the multiplexor starting up subordinate shell and terminal-emulator processes on the fly and compositing the lower screen buffers. But I didn't set out to reinvent screen/tmux. I set out to do virtual terminals in user-space instead of the kernel, with application mode code almost none of which (apart from the stuff that grants access to the framebuffer and keyboard devices) needs or runs with superuser privileges, and where the components are isolated even from one another.
See the StackExchange answer that I hyperlinked to for more on the actual terminal emulation part.
For other people that might be reading: the main difference between these projects is that 3mux is a tmux replacement, while tilish is a tmux plugin. Thus, 3mux is a much larger and more complex undertaking, but you can more easily get tilish up and running anywhere (just copy over a tmux.conf).
But I believe both have the same motivation: "porting" the i3wm user experience and keybindings to terminals. 3mux is also very cool, and I'll be keeping an eye on it myself :).
If you try out tilish, I'd be happy to receive any feedback!
The modifier key seems to be Alt, which is also default on desktop i3 windows manager. I wonder if it's going to interfere - eg. pressing Alt+Enter will simultaneously open new window both in multiplexer and on my desktop?
I think the "escape"-design og screen/tmux is likely better for terminal multiplexing - other "hot-keys" is too likely to collide with terminal programs (never mind window managers/desktops)?
I suppose "super"/"windows"-key combos might be a bit safe from terminal applications - otoh they're likely to collide with window managers...
My understanding is that i3 would intercept the keypress, not passing it onto the terminal. While I want 3mux to work with i3, I decided to choose defaults that appeal to the audience that would need 3mux most (i.e. non-i3 users). I plan to soon make the key bindings configurable.
I agree that non-i3 users need it the most, but have one use case in mind where you might want to combine i3wm + 3mux: remote work. If you ssh into a remote computer, you can not easily spawn new remote terminals. Having one terminal that runs ssh + 3mux lets you use i3wm-like keybindings inside the terminal to open remote splits and tabs with similar keybindings as you would locally. In particular, setting the i3wm $mod to super would make super+enter, super+hjkl, etc. act on local windows, while alt+enter, alt+hjkl, etc. act on remote windows. In a sense, ssh + 3mux would act as a "i3wm-style remote desktop".
If I understand correctly, 3mux does not have session management, but combining 3mux with abduco or dtach should solve that. (And arguably be a more Unix-philosphy solution.)
I think the best way to combine i3wm and 3mux would however be to change the i3wm $mod to win/super, instead of trying to use different modifiers in 3mux. As far as I know, no common terminals support other modifiers than ctrl and alt, and ctrl would collide with most terminal programs. (In tilish, I ended up offering a prefix key as an alternative to alt for people using Kakoune or Emacs.)
My favorite is dvtm. The main reason is how it handles scrolling and selecting content: by opening the buffer in Vim. This is really powerful because it also lets me do anything Vim does, including saving parts of a command's output directly to a file, after cutting out irrelevant parts.
But this looks like a great project too - using WM-like shortcuts in a terminal multiplexer works really well.
Can you (easily) nest 3mux like tmux with (auto-)grouped sessions to produce a (max) 9x9 "grid" of windows to organize your remote hosts, and their windows into an easily accessible structure.
(I use this to be able to reach any window in any other terminal window on any host with max 4 keypresses)
The biggest thing stored by 3mux should be the state of the terminal screen, so memory usage should be negligible.
> Can you (easily) nest 3mux like tmux with (auto-)grouped sessions to produce a (max) 9x9 "grid" of windows to organize your remote hosts, and their windows into an easily accessible structure. (I use this to be able to reach any window in any other terminal window on any host with max 4 keypresses)
This is an awfully specific request. However, I plan to soon add support for workspaces, which should give the user access to, for example, 40 panes within 2 keypresses, given a hypothetical 10 workspaces and 4 panes per workspace.
> Why choose Go? Just curious.
Good question! I chose Go for its go routines and channels. I somewhat wish I used Rust simply because of its elegance. 3mux's performance bottleneck right now is completely IO, so I don't think moving to Rust would make a noticeable difference to the end user apart from the installation process.
I described my workflow, because since I discovered automatically grouped sessions on TMUX, I'd never want to use a terminal multiplexer without that, or comparable functionality.
What I do:
* Open new terminal with a hot-key
* This terminal automatically joins my local (default) session group
* All windows in this session group are now available
* Most windows connect to remote TMUXs
* With CTRL+ 4 keypresses I can navigate to any preexisting window/session, or create a new one locally (or on a remote host)
* After using the window, either i close the terminal, and/or the window, depending on if i want to keep this one.
* On the remote end, people can join my sessions, and can independently of me navigate in the remote window space.
* if I need to concurrently see two (probably different) windows of my local/remote window grid, I just open/auto-attach another terminal.
* the above makes it easy to "place another live tmux view" on a screen different than my main screen, for presentation, or teaching purposes.
Everybody (who previously used tmux in non-grouped mode) I've shown/explained this setup to, has setup their environment just like it afterwards.
I have been thinking about something like this as well. My idea however was to integrate sway/i3 and your terminal of preference (kitty here) with your server over ssh or using eternal terminal. My idea was to simply open new terminal windows already attached to the session and remember their location. I haven't thought about it thoroughly, but this seems like a good alternative for the time being. Might give it a shot on Tuesday at work :)
Excellent!!!
I think this is exactly what I have been wishing for (fro quite some time now)!
I am not quite ready to make the switch to i3 as a WM, (I'm still fairly 'new' in the Ubuntu world, so still need the GUI to help me find settings that I don't know the name of thus how to access via a CLI) this brings me all the great features for my terminal (just like you stated).
This is now the first item on my TODO list for testing new SW :-)
You should give https://regolith-linux.org/ a try. It's a Ubuntu based distro with i3 as WM. They have polished a few things here and there so you have icons for WiFi and easy access to settings.
Just used the PPA. Looks very nice. Has some very nice defaults. Super-Shift-? to get the keybinds was a great idea. I did hit one snag: I can't figure out how to run any actual programs. With the remapping of Super-d to pull up display settings, I am not seeing anything that will pop up an equivalent to dmenu.
I saw that on the web page. All I needed to know, minus how to get the bar on the top. The Action|Keybinding menu that comes up on first launch is simply too tall to fit on my laptop screen; the most important section Launch is off screen if I don't close several of the others. All in all, though, I'm very impressed with it.
The quality of a terminal multiplexor is is in part determined by the quality of the terminal emulation. Unfortunately, this one leaves a lot out.
* The ECMA-35/ECMA-48 escape sequence and control sequence processing is wrong. It is a common error made by people who have read escape sequence lists, but the actual way to process output to a terminal involves a proper state machine, which handles all sequences, even unknown private ones. ECMA-35 and ECMA-48 define ranges of Intermediate, Parameter, and Final characters. One needs to handle the succession of such characters fully, otherwise one ends up like Konsole, which breaks when given some control sequences, erroneously displaying part of the control sequence as text.
* In that same vein, the actual code for CSI is U+009B. The ESC plus open square bracket sequence is a 7-bit alias, from when the world was not 8-bit clean. That 7-bit world hasn't been the case since the late 1970s. There is a whole range of control characters from U+0080 to U+009F.
* Continuing in that vein, the correct terminator for OSC is ST, U+009C. There are moreover rules about ESC, CAN, SUB, CSI, OSC, PM, DSC, and so forth occurring partway through control sequences.
* Even more: The actual code for Reverse Index is U+008D. The ESC plus M sequence is but another 7-bit alias. For best results, translate the entire set of 7-bit aliases into the actual C1 control characters and handle them in their true 8-bit clean forms. It's a simple addition calcuation. It's silly that people write terminal emulators in the 21st century that are decades past the years of not being 8-bit clean, and that handle Unicode, that nonetheless still recognise only the 7-bit alias forms of escape and control sequences as if we still live in a 7-bit world.
* Just don't work from the console_codes manual page for Linux. At all. That documents an idiosyncratic, very limited, and in some famous places downright wrong terminal emulator. I set out explicitly to provide the feature set of that terminal emulator. You should not have to. Use ECMA-48, ECMA-35, and ITU T.416.
* Several years ago people started coming around to the reality that SGR 38 and SGR 48 were supposed to take colon-separated subparameters, not semicolon-separated parameters. The world has been gradually rectifying an almost 30-year-old error. The correct source of information is ITU T.416, not Wikipedia.
* On the positive side, note that this terminal emulator does not have zero meaning default. Zero means zero. This is a good thing. Zero meaning default went away entirely in 1991, and was superseded in 1986. But note that various test programs haven't progressed past 1976. Particularly, note that several of the tests in vttest will fail when zero means zero. (I myself just implemented Mode 22 for getting vttest to work, even though technically Mode 22 has been deprecated since 1991.)
* Although many modern terminal emulators agree on not providing blink any more, the reason for not supporting blink (wasted battery power continually blinking parts of a framebuffer) does not apply to something that renders onto an outer terminal rather than onto a GUI. Let the outer terminal emulator make this decision.
* A lack of reverse video is a shame, and there isn't a reason for not having it represented internally at least. However, it is non-trivial to pass through. Only Konsole really gets it right, and some terminal emulators get it profoundly wrong. Interix cannot turn only it off, (U)RXVT decides to do something completely other than reverse video sometimes, and PuTTY erases using the wrong colour when reverse video is on.
* In that vein, note that several terminal emulators support subparameters to SGR 4 nowadays, giving different underline styles, including curly (SGR 4:3) and dotted (SGR 4:4) amongst others. Mine does, as does kitty (not KiTTY). The Windows Terminal people have it on their to-do list.
* You'll find that there are still outer terminals that do not support SGR 38:5/SGR 48:5 and there are still outer terminals that do not support SGR 38:2/SGR 48:2. One actually has to translate colour systems.
* "hard refresh" misses out a lot that a full-screen TUI program needs to do, from unsetting origin mode and margins, through resetting the cursor shape, to turning off automatic right margin and erase colour mode.
* People will complain about lack of DECSCUSR support. VIM, NeoVIM, and others do make use of it, including several XTerm extensions to it. And this will highlight the aforementioned deficiciencies in the control/escape sequence processing model. DECSCUSR is a CSI-begun control sequence with U+0020 as an intermediate character and U+0071 as the final character.
* People will complain about lack of scrolling region support, too. Full-screen TUI applications that present windows/panes redraw scrolls significantly less efficiently without it.
* Not handling ISO 2022 graphic sets is actually a feature, nowadays. It's a feature of Mosh (q.v.). But again the partial escape sequence processing won't handle this properly. There are several Intermediate characters involved in the G0/G1/G2/G3 designation escape sequences, not solely U+0028. The state machine for decoding them needs to correctly decode all of the Intermediate, Parameter, and Final characters of such a sequence, too.
* Unfortunately, for full keyboard support -- particularly for (U)RXVT, the SCO Console (and derivatives), and Interix as the outer terminal -- one has to add non-standard extensions to ECMA-48. Handling function keys sent from URXVT is particularly egregious. (I myself actually use a patched URXVT, to remedy a couple of its more extreme problems, including a hardwired assumption of 10 function keys.)
* You really don't want to ask the outer terminal for anything other than the new ECMA-48-conformant mouse reports (DEC Private Mode 1006) or the old DEC Locator reports. The other report styles (1005 and 1015) have significant problems. Vanilla URXVT is deficient in this regard, unfortunately.
* It's actually ECMA-48 in both directions, outer terminal input in addition to outer terminal output. DECFNK et al are valid ECMA-48 control sequences, with parameters and a final character. It is a very common error to mishandle them with pattern matching and fixed buffer offsets, but it is an error nonetheless. It's an error that becomes very apparent whey trying to implement modifier recognition. Learn from the pain that users have configuring the recognition of modifiers in pattern-matching systems like GNU Readline, editline, or ZLE. Make it parse ECMA-48 properly, so that parameter recognition in input control sequences just works.
* Deferred wrap should be cancelled by cursor motions.
* Tab stops are set by CTC and HTS. They should not be fixed at every 8 columns.
* Passing the TERM environment variable straight through, whilst otherwise ignoring it, is going to cause no end of problems.
Is this mostly for using w/o i3? I feel like I'm not missing much by using regular terminal windows and letting i3 manage those windows, but I'd love to find out I'm missing something awesome.
Xft.dpi: 192 in ~/.Xresources should do it for most things. I know chromium and firefox do now. However I couldn't get (u)rxvt to scale. The i3 docs [0] also state a font that scales is needed (e.g., *.font: pango:somefont in ~/.Xresources).
"Xft.dpi: 192" in .Xresources is recommended everywhere. However, when the desktop under Xbuntu starts it turns out that this setting has been ignored (or overwritten later). Haven't found out why. Other settings in the same file work as they should.
So this is the standard Xfce desktop, maybe I should try with i3. I use i3 at work, but xfce at home. No exact reason why, maybe it's just good to know more than one systen :)
I'd love to help you solve your issue with i3wm and 4k screens. I'm using i3wm on a 4k monitor for my desktop and 3k for my laptop so I should be able to help you.
I'm a long-time user of i3 (now sway). I wrote this tool to provide the elegance of i3 to terminal users everywhere, especially for people like myself who sometimes use a non-i3 wm or no window manager at all (e.g. when testing code on a bare-bones raspberry pi).
Cheers!