>> That would work. We could actually go all-pull on the protocol and >> have a blocking "poll for new data" command that I send you, if that >> makes life any easier. It's all the same from the client's end. > > Hmm. It all seems much the same to me, in both cases you will block in > poll or select until tmux sends some message. Whether you explicitly > request the message or whether it is just sent doesn't really make much > difference.
I take it back, a block call wouldn't work if we decide we want to send you a message while it's blocking. You should push output to us. Needless to say, it has to be properly interleaved with command output so that it can be parsed unambiguously. > >> >> >> >> // 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. >> > >> > Probably it will assume an empty terminal of the size of the line and >> > draw the line into it using whatever terminal description you like (so >> > long as its on the box running tmux). Then you can render it wherever >> > you like. >> >> This is slightly scary because there's no guarantee at the protocol >> level that the cursor will only stay on one line, but I understand why >> it makes sense; not every emulator implements the same subset of the >> terminal protocol. > > Well, we can tell you the length of the line and then send sequences > limited within that size. I'll have to refactor my vt100 parser, but it's certainly doable. >> >> >> >> >> >> // 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. >> > >> > If you are dealing at the level of panes not windows this won't >> > matter. Panes are never larger or smaller than the window and contain >> > nothing except the application, so you can draw whatever you like >> > outside them. >> >> If a window has exactly one pane then the pane resizes along with the >> window, does it not? Or have I got my terminology wrong? > > It does, yes, but in any case you will be limited to the same area as > the application which is the size of the pane. My original point was a client-initiated resize, resulting in a SIGWINCH, will resize the window, and in turn resize the pane or panes in that window. So we need to be able to tell you that a window changed size. But is it possible to change the size of one window and not another? The GUI will represent each tmux window as a separate native window, and they can of course be resized independently. >> >> >> >> >> >> >> >> >> // 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 >> > >> > Which new output? The raw output from the application or tmux's >> > translated output? >> >> I don't think there's ever a case where you'd perform any >> transformations on a program's output in this system. It should just >> pass it clean through, no? > > If we pass it through unchanged, you will have to write your parser to > understand the tmux terminal description (that is, TERM=screen). Oh, didn't know about TERM=screen. I'd strongly prefer not to write a new terminal parser. Let's stick with re-encoding the output. >> Or do you need to decode it, update your internal state, and re-encode it? > > We'll need to update the internal state so the decode step will not be > optional. > > At the moment there are basically two outputs from this step: > > 1 A set of calls to screen-write.c which update the internal copy for > each pane (its "screen"). > > 2 These pass through to call a set of functions tty_cmd_* which update > the real terminal for all attached clients using the appropriate > terminfo entry. > > There is no reason with a few tweaks the second output can't be > redirected over the wire rather than sent directly to the tty. > > If this isn't necessary we can just tap directly into the read event and > queue up the raw data from the application. > > Whichever we do you will need to provide key input in the same > way. > Perfectly reasonable. >> >> >> > 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. >> > >> > So what I'm leaning to at the moment is you basically have an >> > interaction like this, where => is stuff you send: >> > >> > $ ssh -e none host tmux -C >> > => list-sessions >> > 0: 19 windows (created Fri Oct 29 19:54:56 2010) [170x43] >> > 1: 11 windows (created Fri Oct 29 19:54:56 2010) [80x23] >> > 2: 11 windows (created Fri Oct 29 19:54:56 2010) [80x23] >> > 3: 1 windows (created Thu Nov 11 21:35:22 2010) [170x43] (attached) >> > ^D >> > => list-windows -t 0 >> > 0: ksh [170x43] >> > layout: dfde,170x43,0,0 >> > ^D >> > => list-panes -t 0:0 >> > 0: [170x43] [history 0/2000, 0 bytes] (active) >> > ^D >> > => monitor-pane -t 0:0.0 [new, start sending me events for this pane] >> > ^D >> > => send-keys -t 0:0.0 -p 12 [where "-p size" is new and means read from >> > stream] >> > => xyz abc blah >> > * 0:0.0 data 1000 >> > \033[Hblah blah whatever....... >> > * 0:0.0 move 0:1.0 >> > * 0:1.0 resize 20 30 >> > * 0:1.0 close >> > >> > Not sure about the separator. A preannounced size would be better but >> > that is harder to implement with the existing code. >> >> I agree that specifying the size first makes more sense. Once you have >> to deal with separators, things get complicated with escaping and so >> on. I would prefer to have tmux's output be formatted for easy >> parsing. For instance, instead of: >> >> => list-sessions >> 0: 19 windows (created Fri Oct 29 19:54:56 2010) [170x43] >> 1: 11 windows (created Fri Oct 29 19:54:56 2010) [80x23] >> 2: 11 windows (created Fri Oct 29 19:54:56 2010) [80x23] >> 3: 1 windows (created Thu Nov 11 21:35:22 2010) [170x43] (attached) >> >> say: >> >> => list-sessions >> 0 19 1288407296 170 43 u >> 1 11 1288407296 80 23 u >> 2 11 1288407296 80 23 u >> 3 1 1289540122 170 43 a >> >> This is more to avoid bugs than anything else. Cross-platform date >> parsing, for example, makes me feel a bit uneasy. > > I think two formats seems like an unnecessary maintenance burden but > I'll think about it. May be possible to do it in a way that isn't a mess > of conditionals everywhere there is output. > > We can tweak the output to make it easier to parse if necessary so long > as it remains human readable. > > The asctime() format is mandated by POSIX, it isn't going to change. I'd > prefer something more compact anyway so we can probably use a different > format. I can live with that. >> >> Also, I think we do need to do some escaping, at least in the >> direction of client to server communication. In ssh, for instance, ~ >> has special meaning unless the user turns it off. Many users don't >> know that this exists, and even fewer know they can change the escape >> character. > > Typically you would get the user to tell your program the host and port > and have it run the command, your default command can be something like > "ssh -p $port -e none $host tmux -C". > It worries me that this will cause mysterious breakage and people will regard the feature as unreliable. Or users may decide to start tmux on a host that they're already connected to and don't want to reconnect with -e none. Or more likely, they don't read the documentation and are unaware of passing -e none. An example of where this could go horribly wrong is where a user ssh's to a remote host from within a tmux session and types ~., expecting it to disconnect the "inner" session, but the ~. leaks into the iterm->tmux connection. Inband signaling is evil. ------------------------------------------------------------------------------ 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