> Its probably best to use the tmux terminology if you're talking getting
> stuff out of tmux because that's what it'll use :-).

Having delved a bit deeper, window isn't quite the right term either
as you can have multiple panes in one window. I would prefer to show
each pane in its own tab (eventually I'll support panes that look like
tmux's but we're not there yet). So please substitute Pane for Window
in the API.

>
> Well, this stuff is actually fairly passive.
>
> There are two big problems:
>
> - Asynchronous events. What happens if the user closes a window, or
> moves it to another session, or tmux resizes it? There are going to be a
> lot of places where we need to trigger an event where at the moment we
> just redraw our clients.

If a user closes a window, then the ReadFromWindow() would return EOF,
just like read(2) does.

> - UI side channels that are currently per client not per session. What
> about the status line or if the user tries to enter the command prompt?
> I always regret making this stuff per client but it is there now.

I'm not familiar enough with all the ins and outs of tmux to say, but
my intuition is that we should not expose the command prompt or status
line in this UI. As far as I can tell, the command prompt is used for
UI tasks that would be taken over by my GUI. If it's necessary for the
server to be able to push a status message to the client that would
normally appear in the status bar, I'd say ReadFromPane (formerly
ReadFromWindow) should support out-of-band signaling. In other words,
it'd change to something like:

typedef enum {
  RAW_DATA,   // buffer will be filled in with output from tty
  STATUS_UPDATE   // server is requesting that a message be displayed
to the user
} MessageType;
int ReadFromPane(Pane*, int maxBytes, char* buffer, MessageType* messageType);

We'd pop a dialog box when we get a status update (well, probably
something less annoying than a dialog box, but you get the idea).

> Also I guess you're content to let tmux manage panes.

Please see my correction above - we would manage panes ourselves.

>> // like select(2), but over Windows. Returns a vector of windows where
>> ReadFromWindow() won't block.
>> vector<Window*> GetWindowsWithNewInput();
>
> Yeah but probably you'd be building the data yourself from stuff tmux
> has fed on whatever event channel it has.

Sorry, I don't follow. My thought was that tmux would package up
output from windows into messages that would be sent over our framing
protocol to the client, which would unpack them and determine which
panes have new input. So suppose you have two panes open (either in
one window or in two, it doesn't matter), call them pane0 and pane1.
Suppose pane1 produces output "foo". Then output isomorphic to this
would be sent to stdout by tmux:

message {
  type: raw_data
  sender: pane0
  value: foo
}

My client would read this off the wire and cause
GetPanesWithNewInput() to return a vector containing only pane0.
>> // Returns a single line of text from the nth line of scrollback for a
>> given window. A ScreenCell is a struct with a character, foreground
>> color, background color, etc., representing a single onscreen
>> character.
>> vector<ScreenCell> GetScrollbackHistoryInWindow(Window*, int lineNumber);
>
> What would be most likely is that you would request a line from the
> history and tmux will give you a sequence you can feed into your parser
> to draw it.

Can you define "sequence"? VT100 escape codes are fine as long as any
existing state if taken into account. So if line 0 has a code to
change the foreground color and I request line 1, it must begin with
the foreground color escape code.

>> // Notify window of a size change
>> void ResizeWindow(Window*, int width, int height);
>
> You could actually sort of do this already with force-width and
> force-height options. Basically need to feed your data into the existing
> maximum window size calculations (resize.c).

This is a little messy given the window/pane feature that tmux has and
iTerm2 doesn't. For now I'd probably prefer to do something really
simple like move each pane into its own window when iTerm2 connects
and then use the existing SIGWINCH functionality, so this API would be
unnecessary. If two clients are attached to the same server, tmux does
some presentation work (drawing a "no-man's land" of periods outside
of the window in the second client). I think tmux would have to change
its behavior in this mode to not draw those UI elements and just act
like a window that refuses to resize.

>>
>> // Close a window
>> void CloseWindow(Window*);
>>
>>
>> Does this help clear up what I had in mind?
>
> I'm thinking the right way to do this would be to decouple the display
> side of the client stuff a bit (where the client is the client object in
> the server not the client process). At the moment there are basically a
> few operations:
>
> - Exit (also detach).
> - Lock.
> - Here's an input command (draw line, etc etc).
> - Get the tty size.
> - Redraw everything including the status line.
> - Redraw just the status line.
> - Redraw a single pane.
> - Redraw just the pane borders.
> - Show pane identifiers for N time.
> - Show message (on the status line) for N time.
> - Clear message.
> - Start prompt (on the status line).
> - Clear prompt.
>
> So instead of this, we would start saying "the window has been split" or
> "a window has been closed" or "this window has been resized" and it
> could decide what it needed to redraw or whatever itself.
>

Once iTerm2 is attached, it wouldn't receive instructions to "redraw
the screen" from tmux. You'd send us new output (whatever output you
received wrapped in our protocol), but we'd handle presentation
ourselves. It's possible that tmux's idea of what the screen looks
like would get out of sync with iTerm2's, but those are minor edge
cases (mostly having to do with rewrapping long lines when a window
resizes) that I'm not too concerned about.

> If you look for server_redraw_* in the code it is an idea of where this
> would have to be changed.

I'm going to be on a long plane flight tomorrow, and I plan to spend
it reading tmux code. Hopefully I will come back from vacation able to
speak intelligently about your internals :).

> So what we would do for your idea would be then add a new client type
> that instead of maintaining tty state and updating the tty, passed on
> the event over some channel.
>
> This would allow you to take over the display part of the UI and leave
> tmux doing everything else (key bindings, options, yadda yadda).

I am hopeful that we can move all key bindings into iTerm2 so that
tmux passes 100% of a user's keyboard input cleanly through. My least
favorite part of terminal multiplexers in general is having to
sacrifice a key combination.

> When you want to manipulate or query tmux state I think you could use
> existing tmux commands. It might be nicer to have a set of underlying
> primitives that the commands were based on and that you could invoke but
> that is probably quite a big job.

The existing set of commands covers some nontrivial portion of what I
need, so it seems obvious to me that the protocol we develop should be
based on your existing commands and their syntax.

I think it would be great if this became an established protocol that
other terminal emulators coded to. If this works like I think it will,
it could really change the way people interact with their terminals.

------------------------------------------------------------------------------
Centralized Desktop Delivery: Dell and VMware Reference Architecture
Simplifying enterprise desktop deployment and management using
Dell EqualLogic storage and VMware View: A highly scalable, end-to-end
client virtualization framework. Read more!
http://p.sf.net/sfu/dell-eql-dev2dev
_______________________________________________
tmux-users mailing list
tmux-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tmux-users

Reply via email to