On Thu, Nov 11, 2010 at 02:34:56PM -0800, George Nachman wrote: > On Thu, Nov 11, 2010 at 1:51 PM, Nicholas Marriott > <nicholas.marri...@gmail.com> wrote: > > On Thu, Nov 11, 2010 at 11:10:36AM -0800, George Nachman wrote: > >> > 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. > > > > Note there is stuff that is associated with a window but not a pane like > > the name, title and so on. Although you can get that using the > > list-windows/display-message commands. > > Hopefully the hack of treating a pane like a tab will be temporary > (until I implement pane support in my GUI), so I'll hack up a way to > present the combo of window+pane name. > > > Another thing is that panes are not independently resizable: you can't > > say "I want pane 1 to be 30x20" without affecting other panes around it, > > and the total can't exceed the window size. > > Until I have pane support, this will also be a bit hacky on my end - > I'll probably need to show a pane as a tab with a "no-man's land" > where nothing is drawn.
Fair enough. > > > Also if you try to open a tab for every pane in every window in every > > session you could easily be looking at 200 or so tabs sometimes; there > > will have to be the ability for the user to say "I want only these > > windows from this session". So there will need to be a way for the > > client to say "send me updates only from panes 0:0.1 and 0:1.1". > > > > I'm glad you mentioned that; I would not have guessed anyone would > have 200 shells open at once! I'll have the user pick which window(s) > he wants to attach when he first connects. > Yeah tmux is basically limited by file descriptors and processes, and over a few months it is easy to accumulate dozens of sessions. Even if each has only 5 or 10 windows that is a lot of panes. > >> If a user closes a window, then the ReadFromWindow() would return EOF, > >> just like read(2) does. > > > > It will probably be a push model not a pull so your API can return EOF > > but tmux will have to push something saying it has closed or you will > > never find out (unless you ask for the window list again and compare). > > 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. > > >> >> // 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. > > >> > >> >> // 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. > > >> > >> >> > >> >> // 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). > 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. > > >> > 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. > > 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". ------------------------------------------------------------------------------ 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