I'd like explicit expand/collapse as well so added them back, also with
some trivial renaming of a couple of things I don't like the look of and
a nuclear reformat of the mode-key.c tables. Look ok?


Index: mode-key.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/mode-key.c,v
retrieving revision 1.47
diff -u -p -r1.47 mode-key.c
--- mode-key.c  27 Aug 2012 21:29:23 -0000      1.47
+++ mode-key.c  2 Oct 2012 07:48:30 -0000
@@ -83,6 +83,9 @@ const struct mode_key_cmdstr mode_key_cm
        { MODEKEYCHOICE_SCROLLDOWN, "scroll-down" },
        { MODEKEYCHOICE_SCROLLUP, "scroll-up" },
        { MODEKEYCHOICE_STARTNUMBERPREFIX, "start-number-prefix" },
+       { MODEKEYCHOICE_TREE_COLLAPSE_ALL, "tree-collapse-all" },
+       { MODEKEYCHOICE_TREE_EXPAND_ALL, "tree-expand-all" },
+       { MODEKEYCHOICE_TREE_TOGGLE, "tree-toggle" },
        { MODEKEYCHOICE_UP, "up" },
 
        { 0, NULL }
@@ -138,288 +141,296 @@ const struct mode_key_cmdstr mode_key_cm
 
 /* vi editing keys. */
 const struct mode_key_entry mode_key_vi_edit[] = {
-       { '\003' /* C-c */,     0, MODEKEYEDIT_CANCEL },
-       { '\010' /* C-h */,     0, MODEKEYEDIT_BACKSPACE },
-       { '\011' /* Tab */,     0, MODEKEYEDIT_COMPLETE },
-       { '\025' /* C-u */,     0, MODEKEYEDIT_DELETELINE },
-       { '\027' /* C-w */,     0, MODEKEYEDIT_DELETEWORD },
-       { '\033' /* Escape */,  0, MODEKEYEDIT_SWITCHMODE },
-       { '\r',                 0, MODEKEYEDIT_ENTER },
-       { KEYC_BSPACE,          0, MODEKEYEDIT_BACKSPACE },
-       { KEYC_DC,              0, MODEKEYEDIT_DELETE },
-       { KEYC_DOWN,            0, MODEKEYEDIT_HISTORYDOWN },
-       { KEYC_LEFT,            0, MODEKEYEDIT_CURSORLEFT },
-       { KEYC_RIGHT,           0, MODEKEYEDIT_CURSORRIGHT },
-       { KEYC_UP,              0, MODEKEYEDIT_HISTORYUP },
-       { KEYC_HOME,            0, MODEKEYEDIT_STARTOFLINE },
-       { KEYC_END,             0, MODEKEYEDIT_ENDOFLINE },
-
-       { '$',                  1, MODEKEYEDIT_ENDOFLINE },
-       { '0',                  1, MODEKEYEDIT_STARTOFLINE },
-       { 'A',                  1, MODEKEYEDIT_SWITCHMODEAPPENDLINE },
-       { 'B',                  1, MODEKEYEDIT_PREVIOUSSPACE },
-       { 'D',                  1, MODEKEYEDIT_DELETETOENDOFLINE },
-       { 'E',                  1, MODEKEYEDIT_NEXTSPACEEND },
-       { 'I',                  1, MODEKEYEDIT_SWITCHMODEBEGINLINE },
-       { 'W',                  1, MODEKEYEDIT_NEXTSPACE },
-       { 'X',                  1, MODEKEYEDIT_BACKSPACE },
-       { '\003' /* C-c */,     1, MODEKEYEDIT_CANCEL },
-       { '\010' /* C-h */,     1, MODEKEYEDIT_BACKSPACE },
-       { '\r',                 1, MODEKEYEDIT_ENTER },
-       { '^',                  1, MODEKEYEDIT_STARTOFLINE },
-       { 'a',                  1, MODEKEYEDIT_SWITCHMODEAPPEND },
-       { 'b',                  1, MODEKEYEDIT_PREVIOUSWORD },
-       { 'd',                  1, MODEKEYEDIT_DELETELINE },
-       { 'e',                  1, MODEKEYEDIT_NEXTWORDEND },
-       { 'h',                  1, MODEKEYEDIT_CURSORLEFT },
-       { 'i',                  1, MODEKEYEDIT_SWITCHMODE },
-       { 'j',                  1, MODEKEYEDIT_HISTORYDOWN },
-       { 'k',                  1, MODEKEYEDIT_HISTORYUP },
-       { 'l',                  1, MODEKEYEDIT_CURSORRIGHT },
-       { 'p',                  1, MODEKEYEDIT_PASTE },
-       { 'w',                  1, MODEKEYEDIT_NEXTWORD },
-       { 'x',                  1, MODEKEYEDIT_DELETE },
-       { KEYC_BSPACE,          1, MODEKEYEDIT_BACKSPACE },
-       { KEYC_DC,              1, MODEKEYEDIT_DELETE },
-       { KEYC_DOWN,            1, MODEKEYEDIT_HISTORYDOWN },
-       { KEYC_LEFT,            1, MODEKEYEDIT_CURSORLEFT },
-       { KEYC_RIGHT,           1, MODEKEYEDIT_CURSORRIGHT },
-       { KEYC_UP,              1, MODEKEYEDIT_HISTORYUP },
+       { '\003' /* C-c */,         0, MODEKEYEDIT_CANCEL },
+       { '\010' /* C-h */,         0, MODEKEYEDIT_BACKSPACE },
+       { '\011' /* Tab */,         0, MODEKEYEDIT_COMPLETE },
+       { '\025' /* C-u */,         0, MODEKEYEDIT_DELETELINE },
+       { '\027' /* C-w */,         0, MODEKEYEDIT_DELETEWORD },
+       { '\033' /* Escape */,      0, MODEKEYEDIT_SWITCHMODE },
+       { '\r',                     0, MODEKEYEDIT_ENTER },
+       { KEYC_BSPACE,              0, MODEKEYEDIT_BACKSPACE },
+       { KEYC_DC,                  0, MODEKEYEDIT_DELETE },
+       { KEYC_DOWN,                0, MODEKEYEDIT_HISTORYDOWN },
+       { KEYC_LEFT,                0, MODEKEYEDIT_CURSORLEFT },
+       { KEYC_RIGHT,               0, MODEKEYEDIT_CURSORRIGHT },
+       { KEYC_UP,                  0, MODEKEYEDIT_HISTORYUP },
+       { KEYC_HOME,                0, MODEKEYEDIT_STARTOFLINE },
+       { KEYC_END,                 0, MODEKEYEDIT_ENDOFLINE },
+
+       { '$',                      1, MODEKEYEDIT_ENDOFLINE },
+       { '0',                      1, MODEKEYEDIT_STARTOFLINE },
+       { 'A',                      1, MODEKEYEDIT_SWITCHMODEAPPENDLINE },
+       { 'B',                      1, MODEKEYEDIT_PREVIOUSSPACE },
+       { 'D',                      1, MODEKEYEDIT_DELETETOENDOFLINE },
+       { 'E',                      1, MODEKEYEDIT_NEXTSPACEEND },
+       { 'I',                      1, MODEKEYEDIT_SWITCHMODEBEGINLINE },
+       { 'W',                      1, MODEKEYEDIT_NEXTSPACE },
+       { 'X',                      1, MODEKEYEDIT_BACKSPACE },
+       { '\003' /* C-c */,         1, MODEKEYEDIT_CANCEL },
+       { '\010' /* C-h */,         1, MODEKEYEDIT_BACKSPACE },
+       { '\r',                     1, MODEKEYEDIT_ENTER },
+       { '^',                      1, MODEKEYEDIT_STARTOFLINE },
+       { 'a',                      1, MODEKEYEDIT_SWITCHMODEAPPEND },
+       { 'b',                      1, MODEKEYEDIT_PREVIOUSWORD },
+       { 'd',                      1, MODEKEYEDIT_DELETELINE },
+       { 'e',                      1, MODEKEYEDIT_NEXTWORDEND },
+       { 'h',                      1, MODEKEYEDIT_CURSORLEFT },
+       { 'i',                      1, MODEKEYEDIT_SWITCHMODE },
+       { 'j',                      1, MODEKEYEDIT_HISTORYDOWN },
+       { 'k',                      1, MODEKEYEDIT_HISTORYUP },
+       { 'l',                      1, MODEKEYEDIT_CURSORRIGHT },
+       { 'p',                      1, MODEKEYEDIT_PASTE },
+       { 'w',                      1, MODEKEYEDIT_NEXTWORD },
+       { 'x',                      1, MODEKEYEDIT_DELETE },
+       { KEYC_BSPACE,              1, MODEKEYEDIT_BACKSPACE },
+       { KEYC_DC,                  1, MODEKEYEDIT_DELETE },
+       { KEYC_DOWN,                1, MODEKEYEDIT_HISTORYDOWN },
+       { KEYC_LEFT,                1, MODEKEYEDIT_CURSORLEFT },
+       { KEYC_RIGHT,               1, MODEKEYEDIT_CURSORRIGHT },
+       { KEYC_UP,                  1, MODEKEYEDIT_HISTORYUP },
 
-       { 0,                   -1, 0 }
+       { 0,                       -1, 0 }
 };
 struct mode_key_tree mode_key_tree_vi_edit;
 
 /* vi choice selection keys. */
 const struct mode_key_entry mode_key_vi_choice[] = {
-       { '0' | KEYC_ESCAPE,    0, MODEKEYCHOICE_STARTNUMBERPREFIX },
-       { '1' | KEYC_ESCAPE,    0, MODEKEYCHOICE_STARTNUMBERPREFIX },
-       { '2' | KEYC_ESCAPE,    0, MODEKEYCHOICE_STARTNUMBERPREFIX },
-       { '3' | KEYC_ESCAPE,    0, MODEKEYCHOICE_STARTNUMBERPREFIX },
-       { '4' | KEYC_ESCAPE,    0, MODEKEYCHOICE_STARTNUMBERPREFIX },
-       { '5' | KEYC_ESCAPE,    0, MODEKEYCHOICE_STARTNUMBERPREFIX },
-       { '6' | KEYC_ESCAPE,    0, MODEKEYCHOICE_STARTNUMBERPREFIX },
-       { '7' | KEYC_ESCAPE,    0, MODEKEYCHOICE_STARTNUMBERPREFIX },
-       { '8' | KEYC_ESCAPE,    0, MODEKEYCHOICE_STARTNUMBERPREFIX },
-       { '9' | KEYC_ESCAPE,    0, MODEKEYCHOICE_STARTNUMBERPREFIX },
-       { '\002' /* C-b */,     0, MODEKEYCHOICE_PAGEUP },
-       { '\003' /* C-c */,     0, MODEKEYCHOICE_CANCEL },
-       { '\005' /* C-e */,     0, MODEKEYCHOICE_SCROLLDOWN },
-       { '\006' /* C-f */,     0, MODEKEYCHOICE_PAGEDOWN },
-       { '\031' /* C-y */,     0, MODEKEYCHOICE_SCROLLUP },
-       { '\r',                 0, MODEKEYCHOICE_CHOOSE },
-       { 'j',                  0, MODEKEYCHOICE_DOWN },
-       { 'k',                  0, MODEKEYCHOICE_UP },
-       { 'q',                  0, MODEKEYCHOICE_CANCEL },
-       { KEYC_BSPACE,          0, MODEKEYCHOICE_BACKSPACE },
-       { KEYC_DOWN | KEYC_CTRL,0, MODEKEYCHOICE_SCROLLDOWN },
-       { KEYC_DOWN,            0, MODEKEYCHOICE_DOWN },
-       { KEYC_NPAGE,           0, MODEKEYCHOICE_PAGEDOWN },
-       { KEYC_PPAGE,           0, MODEKEYCHOICE_PAGEUP },
-       { KEYC_UP | KEYC_CTRL,  0, MODEKEYCHOICE_SCROLLUP },
-       { KEYC_UP,              0, MODEKEYCHOICE_UP },
+       { '0' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX },
+       { '1' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX },
+       { '2' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX },
+       { '3' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX },
+       { '4' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX },
+       { '5' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX },
+       { '6' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX },
+       { '7' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX },
+       { '8' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX },
+       { '9' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX },
+       { '\002' /* C-b */,         0, MODEKEYCHOICE_PAGEUP },
+       { '\003' /* C-c */,         0, MODEKEYCHOICE_CANCEL },
+       { '\005' /* C-e */,         0, MODEKEYCHOICE_SCROLLDOWN },
+       { '\006' /* C-f */,         0, MODEKEYCHOICE_PAGEDOWN },
+       { '\031' /* C-y */,         0, MODEKEYCHOICE_SCROLLUP },
+       { '\r',                     0, MODEKEYCHOICE_CHOOSE },
+       { 'j',                      0, MODEKEYCHOICE_DOWN },
+       { 'k',                      0, MODEKEYCHOICE_UP },
+       { 'q',                      0, MODEKEYCHOICE_CANCEL },
+       { KEYC_BSPACE,              0, MODEKEYCHOICE_BACKSPACE },
+       { KEYC_DOWN | KEYC_CTRL,    0, MODEKEYCHOICE_SCROLLDOWN },
+       { KEYC_DOWN,                0, MODEKEYCHOICE_DOWN },
+       { KEYC_NPAGE,               0, MODEKEYCHOICE_PAGEDOWN },
+       { KEYC_PPAGE,               0, MODEKEYCHOICE_PAGEUP },
+       { KEYC_UP | KEYC_CTRL,      0, MODEKEYCHOICE_SCROLLUP },
+       { KEYC_UP,                  0, MODEKEYCHOICE_UP },
+       { ' ',                      0, MODEKEYCHOICE_TREE_TOGGLE },
+       { KEYC_LEFT | KEYC_CTRL,    0, MODEKEYCHOICE_TREE_COLLAPSE_ALL },
+       { KEYC_RIGHT | KEYC_CTRL,   0, MODEKEYCHOICE_TREE_EXPAND_ALL },
 
-       { 0,                    -1, 0 }
+       { 0,                       -1, 0 }
 };
 struct mode_key_tree mode_key_tree_vi_choice;
 
 /* vi copy mode keys. */
 const struct mode_key_entry mode_key_vi_copy[] = {
-       { ' ',                  0, MODEKEYCOPY_STARTSELECTION },
-       { '$',                  0, MODEKEYCOPY_ENDOFLINE },
-       { ',',                  0, MODEKEYCOPY_JUMPREVERSE },
-       { ';',                  0, MODEKEYCOPY_JUMPAGAIN },
-       { '/',                  0, MODEKEYCOPY_SEARCHDOWN },
-       { '0',                  0, MODEKEYCOPY_STARTOFLINE },
-       { '1',                  0, MODEKEYCOPY_STARTNUMBERPREFIX },
-       { '2',                  0, MODEKEYCOPY_STARTNUMBERPREFIX },
-       { '3',                  0, MODEKEYCOPY_STARTNUMBERPREFIX },
-       { '4',                  0, MODEKEYCOPY_STARTNUMBERPREFIX },
-       { '5',                  0, MODEKEYCOPY_STARTNUMBERPREFIX },
-       { '6',                  0, MODEKEYCOPY_STARTNUMBERPREFIX },
-       { '7',                  0, MODEKEYCOPY_STARTNUMBERPREFIX },
-       { '8',                  0, MODEKEYCOPY_STARTNUMBERPREFIX },
-       { '9',                  0, MODEKEYCOPY_STARTNUMBERPREFIX },
-       { ':',                  0, MODEKEYCOPY_GOTOLINE },
-       { '?',                  0, MODEKEYCOPY_SEARCHUP },
-       { 'B',                  0, MODEKEYCOPY_PREVIOUSSPACE },
-       { 'D',                  0, MODEKEYCOPY_COPYENDOFLINE },
-       { 'E',                  0, MODEKEYCOPY_NEXTSPACEEND },
-       { 'F',                  0, MODEKEYCOPY_JUMPBACK },
-       { 'G',                  0, MODEKEYCOPY_HISTORYBOTTOM },
-       { 'H',                  0, MODEKEYCOPY_TOPLINE },
-       { 'J',                  0, MODEKEYCOPY_SCROLLDOWN },
-       { 'K',                  0, MODEKEYCOPY_SCROLLUP },
-       { 'L',                  0, MODEKEYCOPY_BOTTOMLINE },
-       { 'M',                  0, MODEKEYCOPY_MIDDLELINE },
-       { 'N',                  0, MODEKEYCOPY_SEARCHREVERSE },
-       { 'T',                  0, MODEKEYCOPY_JUMPTOBACK },
-       { 'W',                  0, MODEKEYCOPY_NEXTSPACE },
-       { '\002' /* C-b */,     0, MODEKEYCOPY_PREVIOUSPAGE },
-       { '\003' /* C-c */,     0, MODEKEYCOPY_CANCEL },
-       { '\004' /* C-d */,     0, MODEKEYCOPY_HALFPAGEDOWN },
-       { '\005' /* C-e */,     0, MODEKEYCOPY_SCROLLDOWN },
-       { '\006' /* C-f */,     0, MODEKEYCOPY_NEXTPAGE },
-       { '\010' /* C-h */,     0, MODEKEYCOPY_LEFT },
-       { '\025' /* C-u */,     0, MODEKEYCOPY_HALFPAGEUP },
-       { '\031' /* C-y */,     0, MODEKEYCOPY_SCROLLUP },
-       { '\033' /* Escape */,  0, MODEKEYCOPY_CLEARSELECTION },
-       { '\r',                 0, MODEKEYCOPY_COPYSELECTION },
-       { '^',                  0, MODEKEYCOPY_BACKTOINDENTATION },
-       { 'b',                  0, MODEKEYCOPY_PREVIOUSWORD },
-       { 'e',                  0, MODEKEYCOPY_NEXTWORDEND },
-       { 'f',                  0, MODEKEYCOPY_JUMP },
-       { 'g',                  0, MODEKEYCOPY_HISTORYTOP },
-       { 'h',                  0, MODEKEYCOPY_LEFT },
-       { 'j',                  0, MODEKEYCOPY_DOWN },
-       { 'k',                  0, MODEKEYCOPY_UP },
-       { 'l',                  0, MODEKEYCOPY_RIGHT },
-       { 'n',                  0, MODEKEYCOPY_SEARCHAGAIN },
-       { 't',                  0, MODEKEYCOPY_JUMPTO },
-       { 'q',                  0, MODEKEYCOPY_CANCEL },
-       { 'v',                  0, MODEKEYCOPY_RECTANGLETOGGLE },
-       { 'w',                  0, MODEKEYCOPY_NEXTWORD },
-       { KEYC_BSPACE,          0, MODEKEYCOPY_LEFT },
-       { KEYC_DOWN | KEYC_CTRL,0, MODEKEYCOPY_SCROLLDOWN },
-       { KEYC_DOWN,            0, MODEKEYCOPY_DOWN },
-       { KEYC_LEFT,            0, MODEKEYCOPY_LEFT },
-       { KEYC_NPAGE,           0, MODEKEYCOPY_NEXTPAGE },
-       { KEYC_PPAGE,           0, MODEKEYCOPY_PREVIOUSPAGE },
-       { KEYC_RIGHT,           0, MODEKEYCOPY_RIGHT },
-       { KEYC_UP | KEYC_CTRL,  0, MODEKEYCOPY_SCROLLUP },
-       { KEYC_UP,              0, MODEKEYCOPY_UP },
+       { ' ',                      0, MODEKEYCOPY_STARTSELECTION },
+       { '$',                      0, MODEKEYCOPY_ENDOFLINE },
+       { ',',                      0, MODEKEYCOPY_JUMPREVERSE },
+       { ';',                      0, MODEKEYCOPY_JUMPAGAIN },
+       { '/',                      0, MODEKEYCOPY_SEARCHDOWN },
+       { '0',                      0, MODEKEYCOPY_STARTOFLINE },
+       { '1',                      0, MODEKEYCOPY_STARTNUMBERPREFIX },
+       { '2',                      0, MODEKEYCOPY_STARTNUMBERPREFIX },
+       { '3',                      0, MODEKEYCOPY_STARTNUMBERPREFIX },
+       { '4',                      0, MODEKEYCOPY_STARTNUMBERPREFIX },
+       { '5',                      0, MODEKEYCOPY_STARTNUMBERPREFIX },
+       { '6',                      0, MODEKEYCOPY_STARTNUMBERPREFIX },
+       { '7',                      0, MODEKEYCOPY_STARTNUMBERPREFIX },
+       { '8',                      0, MODEKEYCOPY_STARTNUMBERPREFIX },
+       { '9',                      0, MODEKEYCOPY_STARTNUMBERPREFIX },
+       { ':',                      0, MODEKEYCOPY_GOTOLINE },
+       { '?',                      0, MODEKEYCOPY_SEARCHUP },
+       { 'B',                      0, MODEKEYCOPY_PREVIOUSSPACE },
+       { 'D',                      0, MODEKEYCOPY_COPYENDOFLINE },
+       { 'E',                      0, MODEKEYCOPY_NEXTSPACEEND },
+       { 'F',                      0, MODEKEYCOPY_JUMPBACK },
+       { 'G',                      0, MODEKEYCOPY_HISTORYBOTTOM },
+       { 'H',                      0, MODEKEYCOPY_TOPLINE },
+       { 'J',                      0, MODEKEYCOPY_SCROLLDOWN },
+       { 'K',                      0, MODEKEYCOPY_SCROLLUP },
+       { 'L',                      0, MODEKEYCOPY_BOTTOMLINE },
+       { 'M',                      0, MODEKEYCOPY_MIDDLELINE },
+       { 'N',                      0, MODEKEYCOPY_SEARCHREVERSE },
+       { 'T',                      0, MODEKEYCOPY_JUMPTOBACK },
+       { 'W',                      0, MODEKEYCOPY_NEXTSPACE },
+       { '\002' /* C-b */,         0, MODEKEYCOPY_PREVIOUSPAGE },
+       { '\003' /* C-c */,         0, MODEKEYCOPY_CANCEL },
+       { '\004' /* C-d */,         0, MODEKEYCOPY_HALFPAGEDOWN },
+       { '\005' /* C-e */,         0, MODEKEYCOPY_SCROLLDOWN },
+       { '\006' /* C-f */,         0, MODEKEYCOPY_NEXTPAGE },
+       { '\010' /* C-h */,         0, MODEKEYCOPY_LEFT },
+       { '\025' /* C-u */,         0, MODEKEYCOPY_HALFPAGEUP },
+       { '\031' /* C-y */,         0, MODEKEYCOPY_SCROLLUP },
+       { '\033' /* Escape */,      0, MODEKEYCOPY_CLEARSELECTION },
+       { '\r',                     0, MODEKEYCOPY_COPYSELECTION },
+       { '^',                      0, MODEKEYCOPY_BACKTOINDENTATION },
+       { 'b',                      0, MODEKEYCOPY_PREVIOUSWORD },
+       { 'e',                      0, MODEKEYCOPY_NEXTWORDEND },
+       { 'f',                      0, MODEKEYCOPY_JUMP },
+       { 'g',                      0, MODEKEYCOPY_HISTORYTOP },
+       { 'h',                      0, MODEKEYCOPY_LEFT },
+       { 'j',                      0, MODEKEYCOPY_DOWN },
+       { 'k',                      0, MODEKEYCOPY_UP },
+       { 'l',                      0, MODEKEYCOPY_RIGHT },
+       { 'n',                      0, MODEKEYCOPY_SEARCHAGAIN },
+       { 't',                      0, MODEKEYCOPY_JUMPTO },
+       { 'q',                      0, MODEKEYCOPY_CANCEL },
+       { 'v',                      0, MODEKEYCOPY_RECTANGLETOGGLE },
+       { 'w',                      0, MODEKEYCOPY_NEXTWORD },
+       { KEYC_BSPACE,              0, MODEKEYCOPY_LEFT },
+       { KEYC_DOWN | KEYC_CTRL,    0, MODEKEYCOPY_SCROLLDOWN },
+       { KEYC_DOWN,                0, MODEKEYCOPY_DOWN },
+       { KEYC_LEFT,                0, MODEKEYCOPY_LEFT },
+       { KEYC_NPAGE,               0, MODEKEYCOPY_NEXTPAGE },
+       { KEYC_PPAGE,               0, MODEKEYCOPY_PREVIOUSPAGE },
+       { KEYC_RIGHT,               0, MODEKEYCOPY_RIGHT },
+       { KEYC_UP | KEYC_CTRL,      0, MODEKEYCOPY_SCROLLUP },
+       { KEYC_UP,                  0, MODEKEYCOPY_UP },
 
-       { 0,                    -1, 0 }
+       { 0,                       -1, 0 }
 };
 struct mode_key_tree mode_key_tree_vi_copy;
 
 /* emacs editing keys. */
 const struct mode_key_entry mode_key_emacs_edit[] = {
-       { '\001' /* C-a */,     0, MODEKEYEDIT_STARTOFLINE },
-       { '\002' /* C-b */,     0, MODEKEYEDIT_CURSORLEFT },
-       { '\003' /* C-c */,     0, MODEKEYEDIT_CANCEL },
-       { '\004' /* C-d */,     0, MODEKEYEDIT_DELETE },
-       { '\005' /* C-e */,     0, MODEKEYEDIT_ENDOFLINE },
-       { '\006' /* C-f */,     0, MODEKEYEDIT_CURSORRIGHT },
-       { '\010' /* C-H */,     0, MODEKEYEDIT_BACKSPACE },
-       { '\011' /* Tab */,     0, MODEKEYEDIT_COMPLETE },
-       { '\013' /* C-k */,     0, MODEKEYEDIT_DELETETOENDOFLINE },
-       { '\016' /* C-n */,     0, MODEKEYEDIT_HISTORYDOWN },
-       { '\020' /* C-p */,     0, MODEKEYEDIT_HISTORYUP },
-       { '\024' /* C-t */,     0, MODEKEYEDIT_TRANSPOSECHARS },
-       { '\025' /* C-u */,     0, MODEKEYEDIT_DELETELINE },
-       { '\027' /* C-w */,     0, MODEKEYEDIT_DELETEWORD },
-       { '\031' /* C-y */,     0, MODEKEYEDIT_PASTE },
-       { '\033' /* Escape */,  0, MODEKEYEDIT_CANCEL },
-       { '\r',                 0, MODEKEYEDIT_ENTER },
-       { 'b' | KEYC_ESCAPE,    0, MODEKEYEDIT_PREVIOUSWORD },
-       { 'f' | KEYC_ESCAPE,    0, MODEKEYEDIT_NEXTWORDEND },
-       { 'm' | KEYC_ESCAPE,    0, MODEKEYEDIT_STARTOFLINE },
-       { KEYC_BSPACE,          0, MODEKEYEDIT_BACKSPACE },
-       { KEYC_DC,              0, MODEKEYEDIT_DELETE },
-       { KEYC_DOWN,            0, MODEKEYEDIT_HISTORYDOWN },
-       { KEYC_LEFT,            0, MODEKEYEDIT_CURSORLEFT },
-       { KEYC_RIGHT,           0, MODEKEYEDIT_CURSORRIGHT },
-       { KEYC_UP,              0, MODEKEYEDIT_HISTORYUP },
-       { KEYC_HOME,            0, MODEKEYEDIT_STARTOFLINE },
-       { KEYC_END,             0, MODEKEYEDIT_ENDOFLINE },
+       { '\001' /* C-a */,         0, MODEKEYEDIT_STARTOFLINE },
+       { '\002' /* C-b */,         0, MODEKEYEDIT_CURSORLEFT },
+       { '\003' /* C-c */,         0, MODEKEYEDIT_CANCEL },
+       { '\004' /* C-d */,         0, MODEKEYEDIT_DELETE },
+       { '\005' /* C-e */,         0, MODEKEYEDIT_ENDOFLINE },
+       { '\006' /* C-f */,         0, MODEKEYEDIT_CURSORRIGHT },
+       { '\010' /* C-H */,         0, MODEKEYEDIT_BACKSPACE },
+       { '\011' /* Tab */,         0, MODEKEYEDIT_COMPLETE },
+       { '\013' /* C-k */,         0, MODEKEYEDIT_DELETETOENDOFLINE },
+       { '\016' /* C-n */,         0, MODEKEYEDIT_HISTORYDOWN },
+       { '\020' /* C-p */,         0, MODEKEYEDIT_HISTORYUP },
+       { '\024' /* C-t */,         0, MODEKEYEDIT_TRANSPOSECHARS },
+       { '\025' /* C-u */,         0, MODEKEYEDIT_DELETELINE },
+       { '\027' /* C-w */,         0, MODEKEYEDIT_DELETEWORD },
+       { '\031' /* C-y */,         0, MODEKEYEDIT_PASTE },
+       { '\033' /* Escape */,      0, MODEKEYEDIT_CANCEL },
+       { '\r',                     0, MODEKEYEDIT_ENTER },
+       { 'b' | KEYC_ESCAPE,        0, MODEKEYEDIT_PREVIOUSWORD },
+       { 'f' | KEYC_ESCAPE,        0, MODEKEYEDIT_NEXTWORDEND },
+       { 'm' | KEYC_ESCAPE,        0, MODEKEYEDIT_STARTOFLINE },
+       { KEYC_BSPACE,              0, MODEKEYEDIT_BACKSPACE },
+       { KEYC_DC,                  0, MODEKEYEDIT_DELETE },
+       { KEYC_DOWN,                0, MODEKEYEDIT_HISTORYDOWN },
+       { KEYC_LEFT,                0, MODEKEYEDIT_CURSORLEFT },
+       { KEYC_RIGHT,               0, MODEKEYEDIT_CURSORRIGHT },
+       { KEYC_UP,                  0, MODEKEYEDIT_HISTORYUP },
+       { KEYC_HOME,                0, MODEKEYEDIT_STARTOFLINE },
+       { KEYC_END,                 0, MODEKEYEDIT_ENDOFLINE },
 
-       { 0,                   -1, 0 }
+       { 0,                       -1, 0 }
 };
 struct mode_key_tree mode_key_tree_emacs_edit;
 
 /* emacs choice selection keys. */
 const struct mode_key_entry mode_key_emacs_choice[] = {
-       { '0' | KEYC_ESCAPE,    0, MODEKEYCHOICE_STARTNUMBERPREFIX },
-       { '1' | KEYC_ESCAPE,    0, MODEKEYCHOICE_STARTNUMBERPREFIX },
-       { '2' | KEYC_ESCAPE,    0, MODEKEYCHOICE_STARTNUMBERPREFIX },
-       { '3' | KEYC_ESCAPE,    0, MODEKEYCHOICE_STARTNUMBERPREFIX },
-       { '4' | KEYC_ESCAPE,    0, MODEKEYCHOICE_STARTNUMBERPREFIX },
-       { '5' | KEYC_ESCAPE,    0, MODEKEYCHOICE_STARTNUMBERPREFIX },
-       { '6' | KEYC_ESCAPE,    0, MODEKEYCHOICE_STARTNUMBERPREFIX },
-       { '7' | KEYC_ESCAPE,    0, MODEKEYCHOICE_STARTNUMBERPREFIX },
-       { '8' | KEYC_ESCAPE,    0, MODEKEYCHOICE_STARTNUMBERPREFIX },
-       { '9' | KEYC_ESCAPE,    0, MODEKEYCHOICE_STARTNUMBERPREFIX },
-       { '\003' /* C-c */,     0, MODEKEYCHOICE_CANCEL },
-       { '\016' /* C-n */,     0, MODEKEYCHOICE_DOWN },
-       { '\020' /* C-p */,     0, MODEKEYCHOICE_UP },
-       { '\026' /* C-v */,     0, MODEKEYCHOICE_PAGEDOWN },
-       { '\033' /* Escape */,  0, MODEKEYCHOICE_CANCEL },
-       { '\r',                 0, MODEKEYCHOICE_CHOOSE },
-       { 'q',                  0, MODEKEYCHOICE_CANCEL },
-       { 'v' | KEYC_ESCAPE,    0, MODEKEYCHOICE_PAGEUP },
-       { KEYC_BSPACE,          0, MODEKEYCHOICE_BACKSPACE },
-       { KEYC_DOWN | KEYC_CTRL,0, MODEKEYCHOICE_SCROLLDOWN },
-       { KEYC_DOWN,            0, MODEKEYCHOICE_DOWN },
-       { KEYC_NPAGE,           0, MODEKEYCHOICE_PAGEDOWN },
-       { KEYC_PPAGE,           0, MODEKEYCHOICE_PAGEUP },
-       { KEYC_UP | KEYC_CTRL,  0, MODEKEYCHOICE_SCROLLUP },
-       { KEYC_UP,              0, MODEKEYCHOICE_UP },
+       { '0' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX },
+       { '1' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX },
+       { '2' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX },
+       { '3' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX },
+       { '4' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX },
+       { '5' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX },
+       { '6' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX },
+       { '7' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX },
+       { '8' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX },
+       { '9' | KEYC_ESCAPE,        0, MODEKEYCHOICE_STARTNUMBERPREFIX },
+       { '\003' /* C-c */,         0, MODEKEYCHOICE_CANCEL },
+       { '\016' /* C-n */,         0, MODEKEYCHOICE_DOWN },
+       { '\020' /* C-p */,         0, MODEKEYCHOICE_UP },
+       { '\026' /* C-v */,         0, MODEKEYCHOICE_PAGEDOWN },
+       { '\033' /* Escape */,      0, MODEKEYCHOICE_CANCEL },
+       { '\r',                     0, MODEKEYCHOICE_CHOOSE },
+       { 'q',                      0, MODEKEYCHOICE_CANCEL },
+       { 'v' | KEYC_ESCAPE,        0, MODEKEYCHOICE_PAGEUP },
+       { KEYC_BSPACE,              0, MODEKEYCHOICE_BACKSPACE },
+       { KEYC_DOWN | KEYC_CTRL,    0, MODEKEYCHOICE_SCROLLDOWN },
+       { KEYC_DOWN,                0, MODEKEYCHOICE_DOWN },
+       { KEYC_NPAGE,               0, MODEKEYCHOICE_PAGEDOWN },
+       { KEYC_PPAGE,               0, MODEKEYCHOICE_PAGEUP },
+       { KEYC_UP | KEYC_CTRL,      0, MODEKEYCHOICE_SCROLLUP },
+       { KEYC_UP,                  0, MODEKEYCHOICE_UP },
+       { ' ',                      0, MODEKEYCHOICE_TREE_TOGGLE },
+       { KEYC_LEFT,                0, MODEKEYCHOICE_TREE_COLLAPSE },
+       { KEYC_RIGHT,               0, MODEKEYCHOICE_TREE_EXPAND },
+       { KEYC_LEFT | KEYC_CTRL,    0, MODEKEYCHOICE_TREE_COLLAPSE_ALL },
+       { KEYC_RIGHT | KEYC_CTRL,   0, MODEKEYCHOICE_TREE_EXPAND_ALL },
 
-       { 0,                    -1, 0 }
+       { 0,                       -1, 0 }
 };
 struct mode_key_tree mode_key_tree_emacs_choice;
 
 /* emacs copy mode keys. */
 const struct mode_key_entry mode_key_emacs_copy[] = {
-       { ' ',                  0, MODEKEYCOPY_NEXTPAGE },
-       { ',',                  0, MODEKEYCOPY_JUMPREVERSE },
-       { ';',                  0, MODEKEYCOPY_JUMPAGAIN },
-       { '1' | KEYC_ESCAPE,    0, MODEKEYCOPY_STARTNUMBERPREFIX },
-       { '2' | KEYC_ESCAPE,    0, MODEKEYCOPY_STARTNUMBERPREFIX },
-       { '3' | KEYC_ESCAPE,    0, MODEKEYCOPY_STARTNUMBERPREFIX },
-       { '4' | KEYC_ESCAPE,    0, MODEKEYCOPY_STARTNUMBERPREFIX },
-       { '5' | KEYC_ESCAPE,    0, MODEKEYCOPY_STARTNUMBERPREFIX },
-       { '6' | KEYC_ESCAPE,    0, MODEKEYCOPY_STARTNUMBERPREFIX },
-       { '7' | KEYC_ESCAPE,    0, MODEKEYCOPY_STARTNUMBERPREFIX },
-       { '8' | KEYC_ESCAPE,    0, MODEKEYCOPY_STARTNUMBERPREFIX },
-       { '9' | KEYC_ESCAPE,    0, MODEKEYCOPY_STARTNUMBERPREFIX },
-       { '<' | KEYC_ESCAPE,    0, MODEKEYCOPY_HISTORYTOP },
-       { '>' | KEYC_ESCAPE,    0, MODEKEYCOPY_HISTORYBOTTOM },
-       { 'F',                  0, MODEKEYCOPY_JUMPBACK },
-       { 'N',                  0, MODEKEYCOPY_SEARCHREVERSE },
-       { 'R' | KEYC_ESCAPE,    0, MODEKEYCOPY_TOPLINE },
-       { 'R',                  0, MODEKEYCOPY_RECTANGLETOGGLE },
-       { 'T',                  0, MODEKEYCOPY_JUMPTOBACK },
-       { '\000' /* C-Space */, 0, MODEKEYCOPY_STARTSELECTION },
-       { '\001' /* C-a */,     0, MODEKEYCOPY_STARTOFLINE },
-       { '\002' /* C-b */,     0, MODEKEYCOPY_LEFT },
-       { '\003' /* C-c */,     0, MODEKEYCOPY_CANCEL },
-       { '\005' /* C-e */,     0, MODEKEYCOPY_ENDOFLINE },
-       { '\006' /* C-f */,     0, MODEKEYCOPY_RIGHT },
-       { '\007' /* C-g */,     0, MODEKEYCOPY_CLEARSELECTION },
-       { '\013' /* C-k */,     0, MODEKEYCOPY_COPYENDOFLINE },
-       { '\016' /* C-n */,     0, MODEKEYCOPY_DOWN },
-       { '\020' /* C-p */,     0, MODEKEYCOPY_UP },
-       { '\022' /* C-r */,     0, MODEKEYCOPY_SEARCHUP },
-       { '\023' /* C-s */,     0, MODEKEYCOPY_SEARCHDOWN },
-       { '\026' /* C-v */,     0, MODEKEYCOPY_NEXTPAGE },
-       { '\027' /* C-w */,     0, MODEKEYCOPY_COPYSELECTION },
-       { '\033' /* Escape */,  0, MODEKEYCOPY_CANCEL },
-       { 'N',                  0, MODEKEYCOPY_SEARCHREVERSE },
-       { 'b' | KEYC_ESCAPE,    0, MODEKEYCOPY_PREVIOUSWORD },
-       { 'f',                  0, MODEKEYCOPY_JUMP },
-       { 'f' | KEYC_ESCAPE,    0, MODEKEYCOPY_NEXTWORDEND },
-       { 'g',                  0, MODEKEYCOPY_GOTOLINE },
-       { 'm' | KEYC_ESCAPE,    0, MODEKEYCOPY_BACKTOINDENTATION },
-       { 'n',                  0, MODEKEYCOPY_SEARCHAGAIN },
-       { 'q',                  0, MODEKEYCOPY_CANCEL },
-       { 'r' | KEYC_ESCAPE,    0, MODEKEYCOPY_MIDDLELINE },
-       { 't',                  0, MODEKEYCOPY_JUMPTO },
-       { 'v' | KEYC_ESCAPE,    0, MODEKEYCOPY_PREVIOUSPAGE },
-       { 'w' | KEYC_ESCAPE,    0, MODEKEYCOPY_COPYSELECTION },
-       { KEYC_DOWN | KEYC_CTRL,0, MODEKEYCOPY_SCROLLDOWN },
-       { KEYC_DOWN | KEYC_ESCAPE, 0, MODEKEYCOPY_HALFPAGEDOWN },
-       { KEYC_DOWN,            0, MODEKEYCOPY_DOWN },
-       { KEYC_LEFT,            0, MODEKEYCOPY_LEFT },
-       { KEYC_NPAGE,           0, MODEKEYCOPY_NEXTPAGE },
-       { KEYC_PPAGE,           0, MODEKEYCOPY_PREVIOUSPAGE },
-       { KEYC_RIGHT,           0, MODEKEYCOPY_RIGHT },
-       { KEYC_UP | KEYC_CTRL,  0, MODEKEYCOPY_SCROLLUP },
-       { KEYC_UP | KEYC_ESCAPE, 0, MODEKEYCOPY_HALFPAGEUP },
-       { KEYC_UP,              0, MODEKEYCOPY_UP },
+       { ' ',                      0, MODEKEYCOPY_NEXTPAGE },
+       { ',',                      0, MODEKEYCOPY_JUMPREVERSE },
+       { ';',                      0, MODEKEYCOPY_JUMPAGAIN },
+       { '1' | KEYC_ESCAPE,        0, MODEKEYCOPY_STARTNUMBERPREFIX },
+       { '2' | KEYC_ESCAPE,        0, MODEKEYCOPY_STARTNUMBERPREFIX },
+       { '3' | KEYC_ESCAPE,        0, MODEKEYCOPY_STARTNUMBERPREFIX },
+       { '4' | KEYC_ESCAPE,        0, MODEKEYCOPY_STARTNUMBERPREFIX },
+       { '5' | KEYC_ESCAPE,        0, MODEKEYCOPY_STARTNUMBERPREFIX },
+       { '6' | KEYC_ESCAPE,        0, MODEKEYCOPY_STARTNUMBERPREFIX },
+       { '7' | KEYC_ESCAPE,        0, MODEKEYCOPY_STARTNUMBERPREFIX },
+       { '8' | KEYC_ESCAPE,        0, MODEKEYCOPY_STARTNUMBERPREFIX },
+       { '9' | KEYC_ESCAPE,        0, MODEKEYCOPY_STARTNUMBERPREFIX },
+       { '<' | KEYC_ESCAPE,        0, MODEKEYCOPY_HISTORYTOP },
+       { '>' | KEYC_ESCAPE,        0, MODEKEYCOPY_HISTORYBOTTOM },
+       { 'F',                      0, MODEKEYCOPY_JUMPBACK },
+       { 'N',                      0, MODEKEYCOPY_SEARCHREVERSE },
+       { 'R' | KEYC_ESCAPE,        0, MODEKEYCOPY_TOPLINE },
+       { 'R',                      0, MODEKEYCOPY_RECTANGLETOGGLE },
+       { 'T',                      0, MODEKEYCOPY_JUMPTOBACK },
+       { '\000' /* C-Space */,     0, MODEKEYCOPY_STARTSELECTION },
+       { '\001' /* C-a */,         0, MODEKEYCOPY_STARTOFLINE },
+       { '\002' /* C-b */,         0, MODEKEYCOPY_LEFT },
+       { '\003' /* C-c */,         0, MODEKEYCOPY_CANCEL },
+       { '\005' /* C-e */,         0, MODEKEYCOPY_ENDOFLINE },
+       { '\006' /* C-f */,         0, MODEKEYCOPY_RIGHT },
+       { '\007' /* C-g */,         0, MODEKEYCOPY_CLEARSELECTION },
+       { '\013' /* C-k */,         0, MODEKEYCOPY_COPYENDOFLINE },
+       { '\016' /* C-n */,         0, MODEKEYCOPY_DOWN },
+       { '\020' /* C-p */,         0, MODEKEYCOPY_UP },
+       { '\022' /* C-r */,         0, MODEKEYCOPY_SEARCHUP },
+       { '\023' /* C-s */,         0, MODEKEYCOPY_SEARCHDOWN },
+       { '\026' /* C-v */,         0, MODEKEYCOPY_NEXTPAGE },
+       { '\027' /* C-w */,         0, MODEKEYCOPY_COPYSELECTION },
+       { '\033' /* Escape */,      0, MODEKEYCOPY_CANCEL },
+       { 'N',                      0, MODEKEYCOPY_SEARCHREVERSE },
+       { 'b' | KEYC_ESCAPE,        0, MODEKEYCOPY_PREVIOUSWORD },
+       { 'f',                      0, MODEKEYCOPY_JUMP },
+       { 'f' | KEYC_ESCAPE,        0, MODEKEYCOPY_NEXTWORDEND },
+       { 'g',                      0, MODEKEYCOPY_GOTOLINE },
+       { 'm' | KEYC_ESCAPE,        0, MODEKEYCOPY_BACKTOINDENTATION },
+       { 'n',                      0, MODEKEYCOPY_SEARCHAGAIN },
+       { 'q',                      0, MODEKEYCOPY_CANCEL },
+       { 'r' | KEYC_ESCAPE,        0, MODEKEYCOPY_MIDDLELINE },
+       { 't',                      0, MODEKEYCOPY_JUMPTO },
+       { 'v' | KEYC_ESCAPE,        0, MODEKEYCOPY_PREVIOUSPAGE },
+       { 'w' | KEYC_ESCAPE,        0, MODEKEYCOPY_COPYSELECTION },
+       { KEYC_DOWN | KEYC_CTRL,    0, MODEKEYCOPY_SCROLLDOWN },
+       { KEYC_DOWN | KEYC_ESCAPE,  0, MODEKEYCOPY_HALFPAGEDOWN },
+       { KEYC_DOWN,                0, MODEKEYCOPY_DOWN },
+       { KEYC_LEFT,                0, MODEKEYCOPY_LEFT },
+       { KEYC_NPAGE,               0, MODEKEYCOPY_NEXTPAGE },
+       { KEYC_PPAGE,               0, MODEKEYCOPY_PREVIOUSPAGE },
+       { KEYC_RIGHT,               0, MODEKEYCOPY_RIGHT },
+       { KEYC_UP | KEYC_CTRL,      0, MODEKEYCOPY_SCROLLUP },
+       { KEYC_UP | KEYC_ESCAPE,    0, MODEKEYCOPY_HALFPAGEUP },
+       { KEYC_UP,                  0, MODEKEYCOPY_UP },
 
-       { 0,                    -1, 0 }
+       { 0,                       -1, 0 }
 };
 struct mode_key_tree mode_key_tree_emacs_copy;
 
Index: tmux.h
===================================================================
RCS file: /cvs/src/usr.bin/tmux/tmux.h,v
retrieving revision 1.358
diff -u -p -r1.358 tmux.h
--- tmux.h      25 Sep 2012 07:41:22 -0000      1.358
+++ tmux.h      2 Oct 2012 07:48:07 -0000
@@ -552,6 +552,11 @@ enum mode_key_cmd {
        MODEKEYCHOICE_SCROLLDOWN,
        MODEKEYCHOICE_SCROLLUP,
        MODEKEYCHOICE_STARTNUMBERPREFIX,
+       MODEKEYCHOICE_TREE_COLLAPSE,
+       MODEKEYCHOICE_TREE_COLLAPSE_ALL,
+       MODEKEYCHOICE_TREE_EXPAND,
+       MODEKEYCHOICE_TREE_EXPAND_ALL,
+       MODEKEYCHOICE_TREE_TOGGLE,
        MODEKEYCHOICE_UP,
 
        /* Copy keys. */
@@ -891,12 +896,16 @@ struct window_mode {
 /* Structures for choose mode. */
 struct window_choose_data {
        struct client           *client;
-       struct session          *session;
+       struct session          *session; /* Session of current client. */
+       struct session          *tree_session; /* Session of items in tree. */
        struct format_tree      *ft;
        struct winlink          *wl;
        char                    *ft_template;
        char                    *command;
        u_int                    idx;
+       int                      type;
+#define TREE_WINDOW 0x1
+#define TREE_SESSION 0x2
        int                      pane_id;
 };
 
@@ -904,6 +913,8 @@ struct window_choose_mode_item {
        struct window_choose_data       *wcd;
        char                            *name;
        int                              pos;
+       int                              state;
+#define TREE_EXPANDED 0x1
 };
 
 /* Child window structure. */
Index: window-choose.c
===================================================================
RCS file: /cvs/src/usr.bin/tmux/window-choose.c,v
retrieving revision 1.26
diff -u -p -r1.26 window-choose.c
--- window-choose.c     3 Sep 2012 09:57:57 -0000       1.26
+++ window-choose.c     2 Oct 2012 07:50:04 -0000
@@ -40,6 +40,11 @@ void window_choose_write_line(
 void   window_choose_scroll_up(struct window_pane *);
 void   window_choose_scroll_down(struct window_pane *);
 
+void   window_choose_collapse(struct window_pane *, struct session *);
+void   window_choose_expand(struct window_pane *, struct session *, u_int);
+void   window_choose_collapse_all(struct window_pane *);
+void   window_choose_expand_all(struct window_pane *);
+
 enum window_choose_input_type {
        WINDOW_CHOOSE_NORMAL = -1,
        WINDOW_CHOOSE_GOTO_ITEM,
@@ -60,6 +65,7 @@ struct window_choose_mode_data {
        struct mode_key_data    mdata;
 
        ARRAY_DECL(, struct window_choose_mode_item) list;
+       ARRAY_DECL(, struct window_choose_mode_item) old_list;
        int                     width;
        u_int                   top;
        u_int                   selected;
@@ -89,6 +95,7 @@ window_choose_add(struct window_pane *wp
        item->name = format_expand(wcd->ft, wcd->ft_template);
        item->wcd = wcd;
        item->pos = ARRAY_LENGTH(&data->list) - 1;
+       item->state = 0;
 
        data->width = xsnprintf (tmp, sizeof tmp , "%u", item->pos);
 }
@@ -108,6 +115,9 @@ window_choose_ready(struct window_pane *
        data->callbackfn = callbackfn;
        data->freefn = freefn;
 
+       ARRAY_CONCAT(&data->old_list, &data->list);
+
+       window_choose_collapse_all(wp);
        window_choose_redraw_screen(wp);
 }
 
@@ -127,6 +137,7 @@ window_choose_init(struct window_pane *w
        data->input_prompt = NULL;
 
        ARRAY_INIT(&data->list);
+       ARRAY_INIT(&data->old_list);
        data->top = 0;
 
        s = &data->screen;
@@ -154,9 +165,11 @@ window_choose_data_create(struct cmd_ctx
        wcd->ft_template = NULL;
        wcd->command = NULL;
        wcd->wl = NULL;
+       wcd->tree_session = NULL;
        wcd->client = ctx->curclient;
        wcd->session = ctx->curclient->session;
        wcd->idx = -1;
+       wcd->type = 0;
 
        return (wcd);
 }
@@ -175,6 +188,7 @@ window_choose_free(struct window_pane *w
                free(item->name);
        }
        ARRAY_FREE(&data->list);
+       ARRAY_FREE(&data->old_list);
        free(data->input_str);
 
        screen_free(&data->screen);
@@ -228,6 +242,166 @@ window_choose_prompt_input(enum window_c
        window_choose_redraw_screen(wp);
 }
 
+void
+window_choose_collapse(struct window_pane *wp, struct session *s)
+{
+       struct window_choose_mode_data  *data = wp->modedata;
+       struct window_choose_mode_item  *item, *chosen;
+       struct window_choose_data       *wcd;
+       u_int                            i, pos;
+
+       ARRAY_DECL(, struct window_choose_mode_item) list_copy;
+       ARRAY_INIT(&list_copy);
+
+       pos = data->selected;
+
+       chosen = &ARRAY_ITEM(&data->list, pos);
+       chosen->state &= ~TREE_EXPANDED;
+
+       /*
+        * Trying to mangle the &data->list in-place has lots of problems, so
+        * assign the actual result we want to render and copy the new one over
+        * the top of it.
+        */
+       for (i = 0; i < ARRAY_LENGTH(&data->list); i++)
+       {
+               item = &ARRAY_ITEM(&data->list, i);
+               wcd = item->wcd;
+
+               if (s == wcd->tree_session) {
+                       /* We only show the session when collapsed. */
+                       if (wcd->type & TREE_SESSION) {
+                               item->state &= ~TREE_EXPANDED;
+
+                               ARRAY_ADD(&list_copy,
+                                               ARRAY_ITEM(&data->list, i));
+                               /*
+                                * Update the selection to this session item so
+                                * we don't end up highlighting a non-existent
+                                * item.
+                                */
+                               data->selected = i;
+                       }
+               } else
+                       ARRAY_ADD(&list_copy, ARRAY_ITEM(&data->list, i));
+       }
+
+       if (!ARRAY_EMPTY(&list_copy)) {
+               ARRAY_FREE(&data->list);
+               ARRAY_CONCAT(&data->list, &list_copy);
+       }
+}
+
+void
+window_choose_collapse_all(struct window_pane *wp)
+{
+       struct window_choose_mode_data  *data = wp->modedata;
+       struct window_choose_mode_item  *item, *chosen;
+       struct session                  *s;
+       u_int                            i;
+
+       chosen = &ARRAY_ITEM(&data->list, data->selected);
+
+       RB_FOREACH(s, sessions, &sessions)
+               window_choose_collapse(wp, s);
+
+       /* Reset the selection back to the starting session. */
+       for (i = 0; i < ARRAY_LENGTH(&data->list); i++) {
+               item = &ARRAY_ITEM(&data->list, i);
+
+               if (chosen->wcd->session != item->wcd->tree_session)
+                       continue;
+
+               if (item->wcd->type & TREE_SESSION)
+                       data->selected = i;
+       }
+       window_choose_redraw_screen(wp);
+}
+
+void
+window_choose_expand_all(struct window_pane *wp)
+{
+       struct window_choose_mode_data  *data = wp->modedata;
+       struct window_choose_mode_item  *item;
+       struct session                  *s;
+       u_int                            i;
+
+       RB_FOREACH(s, sessions, &sessions) {
+               for (i = 0; i < ARRAY_LENGTH(&data->list); i++) {
+                       item = &ARRAY_ITEM(&data->list, i);
+
+                       if (s != item->wcd->tree_session)
+                               continue;
+
+                       if (item->wcd->type & TREE_SESSION)
+                               window_choose_expand(wp, s, i);
+               }
+       }
+
+       window_choose_redraw_screen(wp);
+}
+
+void
+window_choose_expand(struct window_pane *wp, struct session *s, u_int pos)
+{
+       struct window_choose_mode_data  *data = wp->modedata;
+       struct window_choose_mode_item  *item, *chosen;
+       struct window_choose_data       *wcd;
+       u_int                            i, items;
+
+       chosen = &ARRAY_ITEM(&data->list, pos);
+       items = ARRAY_LENGTH(&data->old_list) - 1;
+
+       /* It's not possible to expand anything other than sessions. */
+       if (!(chosen->wcd->type & TREE_SESSION))
+               return;
+
+       /* Don't re-expand a session which is already expanded. */
+       if (chosen->state & TREE_EXPANDED)
+               return;
+
+       /* Mark the session entry as expanded. */
+       chosen->state |= TREE_EXPANDED;
+
+       /*
+        * Go back through the original list of all sessions and windows, and
+        * pull out the windows where the session matches the selection chosen
+        * to expand.
+        */
+       for (i = items; i > 0; i--) {
+               item = &ARRAY_ITEM(&data->old_list, i);
+               item->state |= TREE_EXPANDED;
+               wcd = item->wcd;
+
+               if (s == wcd->tree_session) {
+                       /*
+                        * Since the session is already displayed, we only care
+                        * to add back in window for it.
+                        */
+                       if (wcd->type & TREE_WINDOW) {
+                               /*
+                                * If the insertion point for adding the
+                                * windows to the session falls inside the
+                                * range of the list, then we insert these
+                                * entries in order *AFTER* the selected
+                                * session.
+                                */
+                               if (pos < i ) {
+                                       ARRAY_INSERT(&data->list,
+                                           pos + 1,
+                                           ARRAY_ITEM(&data->old_list,
+                                           i));
+                               } else {
+                                       /* Ran out of room, add to the end. */
+                                       ARRAY_ADD(&data->list,
+                                           ARRAY_ITEM(&data->old_list,
+                                           i));
+                               }
+                       }
+               }
+       }
+}
+
 /* ARGSUSED */
 void
 window_choose_key(struct window_pane *wp, unused struct session *sess, int key)
@@ -237,7 +411,7 @@ window_choose_key(struct window_pane *wp
        struct screen_write_ctx          ctx;
        struct window_choose_mode_item  *item;
        size_t                           input_len;
-       u_int                            items, n;
+       u_int                            items, n;
        int                              idx;
 
        items = ARRAY_LENGTH(&data->list);
@@ -285,6 +459,37 @@ window_choose_key(struct window_pane *wp
                window_choose_fire_callback(wp, item->wcd);
                window_pane_reset_mode(wp);
                break;
+       case MODEKEYCHOICE_TREE_TOGGLE:
+               item = &ARRAY_ITEM(&data->list, data->selected);
+               if (item->state & TREE_EXPANDED)
+                       window_choose_collapse(wp, item->wcd->tree_session);
+               else {
+                       window_choose_expand(wp, item->wcd->tree_session,
+                           data->selected);
+               }
+               window_choose_redraw_screen(wp);
+               break;
+       case MODEKEYCHOICE_TREE_COLLAPSE:
+               item = &ARRAY_ITEM(&data->list, data->selected);
+               if (item->state & TREE_EXPANDED) {
+                       window_choose_collapse(wp, item->wcd->tree_session);
+                       window_choose_redraw_screen(wp);
+               }
+               break;
+       case MODEKEYCHOICE_TREE_COLLAPSE_ALL:
+               window_choose_collapse_all(wp);
+               break;
+       case MODEKEYCHOICE_TREE_EXPAND:
+               item = &ARRAY_ITEM(&data->list, data->selected);
+               if (!(item->state & TREE_EXPANDED)) {
+                       window_choose_expand(wp, item->wcd->tree_session,
+                           data->selected);
+                       window_choose_redraw_screen(wp);
+               }
+               break;
+       case MODEKEYCHOICE_TREE_EXPAND_ALL:
+               window_choose_expand_all(wp);
+               break;
        case MODEKEYCHOICE_UP:
                if (items == 0)
                        break;
@@ -469,7 +674,13 @@ window_choose_write_line(
                else
                        xsnprintf (label, sizeof label, "(%d)", item->pos);
                screen_write_nputs(ctx, screen_size_x(s) - 1, &gc, utf8flag,
-                   "%*s %s", data->width + 2, label, item->name);
+                   "%*s %s %s", data->width + 2, label,
+                   /*
+                    * Add indication to tree if necessary about whether it's
+                    * expanded or not.
+                    */
+                   (item->wcd->type & TREE_SESSION) ?
+                   (item->state & TREE_EXPANDED ? "-" : "+") : "", item->name);
        }
        while (s->cx < screen_size_x(s))
                screen_write_putc(ctx, &gc, ' ');
@@ -623,6 +834,8 @@ window_choose_add_session(struct window_
 
        wcd = window_choose_data_create(ctx);
        wcd->idx = s->idx;
+       wcd->tree_session = s;
+       wcd->type = TREE_SESSION;
        wcd->command = cmd_template_replace(action, s->name, 1);
        wcd->ft_template = xstrdup(template);
        format_add(wcd->ft, "line", "%u", idx);
@@ -684,6 +897,8 @@ window_choose_add_window(struct window_p
 
        wcd->idx = wl->idx;
        wcd->wl = wl;
+       wcd->tree_session = s;
+       wcd->type = TREE_WINDOW;
        wcd->ft_template = xstrdup(template);
        format_add(wcd->ft, "line", "%u", idx);
        format_session(wcd->ft, s);






On Mon, Oct 01, 2012 at 01:24:46PM +0100, Thomas Adam wrote:
> This patch adds the ability to expand/collapse a single session using the
> spacebar.
> 
> Likewise, C-Left and C-Right will collapse and expand all sessions,
> respectively.
> ---
>  This is the second version of the original patch, which takes Romain's
>  suggestion.  Now, spacebar will expand/collapse a single session.  There is
>  no longer explicit expand/collapse bindings -- only COLLAPSE_EXPAND_TOGGLE.
> 
>  Fixed a minor bug with selecting sessions after collapsing them too.
> 
>  I've still left the bindings for expand_all and collapse_all unchanged --
>  if they need to change, feel free to do so.   I suppose I'll have to update
>  the man page?
> 
>  mode-key.c      |   9 +++
>  tmux.h          |  11 ++-
>  window-choose.c | 206 
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  3 files changed, 223 insertions(+), 3 deletions(-)
> 
> diff --git a/mode-key.c b/mode-key.c
> index cacdb91..887abf4 100644
> --- a/mode-key.c
> +++ b/mode-key.c
> @@ -77,7 +77,10 @@ const struct mode_key_cmdstr mode_key_cmdstr_choice[] = {
>       { MODEKEYCHOICE_BACKSPACE, "backspace" },
>       { MODEKEYCHOICE_CANCEL, "cancel" },
>       { MODEKEYCHOICE_CHOOSE, "choose" },
> +     { MODEKEYCHOICE_COLLAPSE_ALL, "collapse-all" },
> +     { MODEKEYCHOICE_COLLAPSE_EXPAND_TOGGLE, "collapse-toggle" },
>       { MODEKEYCHOICE_DOWN, "down" },
> +     { MODEKEYCHOICE_EXPAND_ALL, "expand-all" },
>       { MODEKEYCHOICE_PAGEDOWN, "page-down" },
>       { MODEKEYCHOICE_PAGEUP, "page-up" },
>       { MODEKEYCHOICE_SCROLLDOWN, "scroll-down" },
> @@ -218,6 +221,9 @@ const struct mode_key_entry mode_key_vi_choice[] = {
>       { KEYC_PPAGE,           0, MODEKEYCHOICE_PAGEUP },
>       { KEYC_UP | KEYC_CTRL,  0, MODEKEYCHOICE_SCROLLUP },
>       { KEYC_UP,              0, MODEKEYCHOICE_UP },
> +     { ' ',                  0, MODEKEYCHOICE_COLLAPSE_EXPAND_TOGGLE },
> +     { KEYC_LEFT | KEYC_CTRL,0, MODEKEYCHOICE_COLLAPSE_ALL },
> +     { KEYC_RIGHT | KEYC_CTRL,0,MODEKEYCHOICE_EXPAND_ALL },
>  
>       { 0,                    -1, 0 }
>  };
> @@ -355,6 +361,9 @@ const struct mode_key_entry mode_key_emacs_choice[] = {
>       { KEYC_PPAGE,           0, MODEKEYCHOICE_PAGEUP },
>       { KEYC_UP | KEYC_CTRL,  0, MODEKEYCHOICE_SCROLLUP },
>       { KEYC_UP,              0, MODEKEYCHOICE_UP },
> +     { ' ',                  0, MODEKEYCHOICE_COLLAPSE_EXPAND_TOGGLE },
> +     { KEYC_LEFT | KEYC_CTRL,0, MODEKEYCHOICE_COLLAPSE_ALL },
> +     { KEYC_RIGHT | KEYC_CTRL,0,MODEKEYCHOICE_EXPAND_ALL },
>  
>       { 0,                    -1, 0 }
>  };
> diff --git a/tmux.h b/tmux.h
> index c18499b..25d5bf5 100644
> --- a/tmux.h
> +++ b/tmux.h
> @@ -542,7 +542,10 @@ enum mode_key_cmd {
>       MODEKEYCHOICE_BACKSPACE,
>       MODEKEYCHOICE_CANCEL,
>       MODEKEYCHOICE_CHOOSE,
> +     MODEKEYCHOICE_COLLAPSE_ALL,
> +     MODEKEYCHOICE_COLLAPSE_EXPAND_TOGGLE,
>       MODEKEYCHOICE_DOWN,
> +     MODEKEYCHOICE_EXPAND_ALL,
>       MODEKEYCHOICE_PAGEDOWN,
>       MODEKEYCHOICE_PAGEUP,
>       MODEKEYCHOICE_SCROLLDOWN,
> @@ -887,12 +890,16 @@ struct window_mode {
>  /* Structures for choose mode. */
>  struct window_choose_data {
>       struct client           *client;
> -     struct session          *session;
> +     struct session          *session; /* Session of current client. */
> +     struct session          *tree_session; /* Session of items in tree. */
>       struct format_tree      *ft;
>       struct winlink          *wl;
>       char                    *ft_template;
>       char                    *command;
>       u_int                    idx;
> +     int                      type;
> +#define TREE_WINDOW 0x1
> +#define TREE_SESSION 0x2
>       int                      pane_id;
>  };
>  
> @@ -900,6 +907,8 @@ struct window_choose_mode_item {
>       struct window_choose_data       *wcd;
>       char                            *name;
>       int                              pos;
> +     int                              state;
> +#define TREE_EXPANDED 0x1
>  };
>  
>  /* Child window structure. */
> diff --git a/window-choose.c b/window-choose.c
> index c77a1d3..acde980 100644
> --- a/window-choose.c
> +++ b/window-choose.c
> @@ -40,6 +40,12 @@ void       window_choose_write_line(
>  void window_choose_scroll_up(struct window_pane *);
>  void window_choose_scroll_down(struct window_pane *);
>  
> +void window_choose_collapse(struct window_pane *, struct session *);
> +void window_choose_expand(struct window_pane *, struct session *, u_int);
> +
> +void window_choose_collapse_all(struct window_pane *);
> +void window_choose_expand_all(struct window_pane *);
> +
>  enum window_choose_input_type {
>       WINDOW_CHOOSE_NORMAL = -1,
>       WINDOW_CHOOSE_GOTO_ITEM,
> @@ -60,6 +66,7 @@ struct window_choose_mode_data {
>       struct mode_key_data    mdata;
>  
>       ARRAY_DECL(, struct window_choose_mode_item) list;
> +     ARRAY_DECL(, struct window_choose_mode_item) list_orig;
>       int                     width;
>       u_int                   top;
>       u_int                   selected;
> @@ -89,6 +96,7 @@ window_choose_add(struct window_pane *wp, struct 
> window_choose_data *wcd)
>       item->name = format_expand(wcd->ft, wcd->ft_template);
>       item->wcd = wcd;
>       item->pos = ARRAY_LENGTH(&data->list) - 1;
> +     item->state = 0;
>  
>       data->width = xsnprintf (tmp, sizeof tmp , "%u", item->pos);
>  }
> @@ -108,6 +116,9 @@ window_choose_ready(struct window_pane *wp, u_int cur,
>       data->callbackfn = callbackfn;
>       data->freefn = freefn;
>  
> +     ARRAY_CONCAT(&data->list_orig, &data->list);
> +
> +     window_choose_collapse_all(wp);
>       window_choose_redraw_screen(wp);
>  }
>  
> @@ -127,6 +138,7 @@ window_choose_init(struct window_pane *wp)
>       data->input_prompt = NULL;
>  
>       ARRAY_INIT(&data->list);
> +     ARRAY_INIT(&data->list_orig);
>       data->top = 0;
>  
>       s = &data->screen;
> @@ -154,9 +166,11 @@ window_choose_data_create(struct cmd_ctx *ctx)
>       wcd->ft_template = NULL;
>       wcd->command = NULL;
>       wcd->wl = NULL;
> +     wcd->tree_session = NULL;
>       wcd->client = ctx->curclient;
>       wcd->session = ctx->curclient->session;
>       wcd->idx = -1;
> +     wcd->type = 0;
>  
>       return (wcd);
>  }
> @@ -175,6 +189,7 @@ window_choose_free(struct window_pane *wp)
>               free(item->name);
>       }
>       ARRAY_FREE(&data->list);
> +     ARRAY_FREE(&data->list_orig);
>       free(data->input_str);
>  
>       screen_free(&data->screen);
> @@ -228,6 +243,168 @@ window_choose_prompt_input(enum 
> window_choose_input_type input_type,
>       window_choose_redraw_screen(wp);
>  }
>  
> +void
> +window_choose_collapse(struct window_pane *wp, struct session *s)
> +{
> +     struct window_choose_mode_data  *data = wp->modedata;
> +     struct window_choose_mode_item  *item, *chosen;
> +     struct window_choose_data       *wcd;
> +     u_int                            i, pos;
> +
> +     ARRAY_DECL(, struct window_choose_mode_item) list_copy;
> +     ARRAY_INIT(&list_copy);
> +
> +     pos = data->selected;
> +
> +     chosen = &ARRAY_ITEM(&data->list, pos);
> +     chosen->state &= ~TREE_EXPANDED;
> +
> +     /*
> +      * Trying to mangle the &data->list in-place has lots of problems, so
> +      * assign the actual result we want to render and copy the new one
> +      * over the top of it.
> +      */
> +     for (i = 0; i < ARRAY_LENGTH(&data->list); i++)
> +     {
> +             item = &ARRAY_ITEM(&data->list, i);
> +             wcd = item->wcd;
> +
> +             if (s == wcd->tree_session) {
> +                     /* We only show the session when collapsed. */
> +                     if (wcd->type & TREE_SESSION) {
> +                             item->state &= ~TREE_EXPANDED;
> +
> +                             ARRAY_ADD(&list_copy,
> +                                             ARRAY_ITEM(&data->list, i));
> +                             /*
> +                              * Update the selection to this session item
> +                              * so we don't end up highlighting a
> +                              * non-existent item.
> +                              */
> +                             data->selected = i;
> +                     }
> +             } else
> +                     ARRAY_ADD(&list_copy, ARRAY_ITEM(&data->list, i));
> +     }
> +
> +     if (!ARRAY_EMPTY(&list_copy)) {
> +             ARRAY_FREE(&data->list);
> +             ARRAY_CONCAT(&data->list, &list_copy);
> +     }
> +}
> +
> +void
> +window_choose_collapse_all(struct window_pane *wp)
> +{
> +     struct window_choose_mode_data  *data = wp->modedata;
> +     struct window_choose_mode_item  *item, *chosen;
> +     struct session                  *s;
> +     u_int                            i;
> +
> +     chosen = &ARRAY_ITEM(&data->list, data->selected);
> +
> +     RB_FOREACH(s, sessions, &sessions)
> +             window_choose_collapse(wp, s);
> +
> +     /* Reset the selection back to the starting session. */
> +     for (i = 0; i < ARRAY_LENGTH(&data->list); i++)
> +     {
> +             item = &ARRAY_ITEM(&data->list, i);
> +
> +             if (chosen->wcd->session != item->wcd->tree_session)
> +                     continue;
> +
> +             if (item->wcd->type & TREE_SESSION)
> +                     data->selected = i;
> +     }
> +     window_choose_redraw_screen(wp);
> +}
> +
> +void
> +window_choose_expand_all(struct window_pane *wp)
> +{
> +     struct window_choose_mode_data  *data = wp->modedata;
> +     struct window_choose_mode_item  *item;
> +     struct session                  *s;
> +     u_int                            i;
> +
> +     RB_FOREACH(s, sessions, &sessions) {
> +             for (i = 0; i < ARRAY_LENGTH(&data->list); i++)
> +             {
> +                     item = &ARRAY_ITEM(&data->list, i);
> +
> +                     if (s != item->wcd->tree_session)
> +                             continue;
> +
> +                     if (item->wcd->type & TREE_SESSION)
> +                             window_choose_expand(wp, s, i);
> +             }
> +     }
> +
> +     window_choose_redraw_screen(wp);
> +}
> +
> +void
> +window_choose_expand(struct window_pane *wp, struct session *s, u_int pos)
> +{
> +     struct window_choose_mode_data  *data = wp->modedata;
> +     struct window_choose_mode_item  *item, *chosen;
> +     struct window_choose_data       *wcd;
> +     u_int                            i, items;
> +
> +     chosen = &ARRAY_ITEM(&data->list, pos);
> +     items = ARRAY_LENGTH(&data->list_orig) - 1;
> +
> +     /* It's not possible to expand anything other than sessions. */
> +     if (!(chosen->wcd->type & TREE_SESSION))
> +             return;
> +
> +     /* Don't re-expand a session which is already expanded. */
> +     if (chosen->state & TREE_EXPANDED)
> +             return;
> +
> +     /* Mark the session entry as expanded. */
> +     chosen->state |= TREE_EXPANDED;
> +
> +     /*
> +      * Go back through the original list of all sessions and windows, and
> +      * pull out the windows where the session matches the selection chosen
> +      * to expand.
> +      */
> +     for (i = items; i > 0; i--)
> +     {
> +             item = &ARRAY_ITEM(&data->list_orig, i);
> +             item->state |= TREE_EXPANDED;
> +             wcd = item->wcd;
> +
> +             if (s == wcd->tree_session) {
> +                     /*
> +                      * Since the session is already displayed, we only
> +                      * care to add back in window for it.
> +                      */
> +                     if (wcd->type & TREE_WINDOW) {
> +                             /* If the insertion point for adding the
> +                              * windows to the session falls inside the
> +                              * range of the list, then we insert these
> +                              * entries in order *AFTER* the selected
> +                              * session.
> +                              */
> +                             if (pos < i ) {
> +                                     ARRAY_INSERT(&data->list, pos + 1,
> +                                             ARRAY_ITEM(&data->list_orig,
> +                                             i));
> +                             } else
> +                                     /*
> +                                      * Ran out of room, add it to the end.
> +                                      */
> +                                     ARRAY_ADD(&data->list,
> +                                             ARRAY_ITEM(&data->list_orig,
> +                                             i));
> +                     }
> +             }
> +     }
> +}
> +
>  /* ARGSUSED */
>  void
>  window_choose_key(struct window_pane *wp, unused struct session *sess, int 
> key)
> @@ -237,7 +414,7 @@ window_choose_key(struct window_pane *wp, unused struct 
> session *sess, int key)
>       struct screen_write_ctx          ctx;
>       struct window_choose_mode_item  *item;
>       size_t                           input_len;
> -     u_int                            items, n;
> +     u_int                            items, n;
>       int                              idx;
>  
>       items = ARRAY_LENGTH(&data->list);
> @@ -285,6 +462,21 @@ window_choose_key(struct window_pane *wp, unused struct 
> session *sess, int key)
>               window_choose_fire_callback(wp, item->wcd);
>               window_pane_reset_mode(wp);
>               break;
> +     case MODEKEYCHOICE_COLLAPSE_EXPAND_TOGGLE:
> +             item = &ARRAY_ITEM(&data->list, data->selected);
> +             if (item->state & TREE_EXPANDED)
> +                     window_choose_collapse(wp, item->wcd->tree_session);
> +             else
> +                     window_choose_expand(wp, item->wcd->tree_session,
> +                                     data->selected);
> +             window_choose_redraw_screen(wp);
> +             break;
> +     case MODEKEYCHOICE_COLLAPSE_ALL:
> +             window_choose_collapse_all(wp);
> +             break;
> +     case MODEKEYCHOICE_EXPAND_ALL:
> +             window_choose_expand_all(wp);
> +             break;
>       case MODEKEYCHOICE_UP:
>               if (items == 0)
>                       break;
> @@ -469,7 +661,13 @@ window_choose_write_line(
>               else
>                       xsnprintf (label, sizeof label, "(%d)", item->pos);
>               screen_write_nputs(ctx, screen_size_x(s) - 1, &gc, utf8flag,
> -                 "%*s %s", data->width + 2, label, item->name);
> +                 "%*s %s %s", data->width + 2, label,
> +                 /*
> +                  * Add indication to tree if necessary about whether it's
> +                  * expanded or not.
> +                  */
> +                 (item->wcd->type & TREE_SESSION) ?
> +                 (item->state & TREE_EXPANDED ? "-" : "+") : "", item->name);
>       }
>       while (s->cx < screen_size_x(s))
>               screen_write_putc(ctx, &gc, ' ');
> @@ -623,6 +821,8 @@ window_choose_add_session(struct window_pane *wp, struct 
> cmd_ctx *ctx,
>  
>       wcd = window_choose_data_create(ctx);
>       wcd->idx = s->idx;
> +     wcd->tree_session = s;
> +     wcd->type = TREE_SESSION;
>       wcd->command = cmd_template_replace(action, s->name, 1);
>       wcd->ft_template = xstrdup(template);
>       format_add(wcd->ft, "line", "%u", idx);
> @@ -684,6 +884,8 @@ window_choose_add_window(struct window_pane *wp, struct 
> cmd_ctx *ctx,
>  
>       wcd->idx = wl->idx;
>       wcd->wl = wl;
> +     wcd->tree_session = s;
> +     wcd->type = TREE_WINDOW;
>       wcd->ft_template = xstrdup(template);
>       format_add(wcd->ft, "line", "%u", idx);
>       format_session(wcd->ft, s);
> -- 
> 1.7.11.4
> 
> 
> ------------------------------------------------------------------------------
> Got visibility?
> Most devs has no idea what their production app looks like.
> Find out how fast your code is with AppDynamics Lite.
> http://ad.doubleclick.net/clk;262219671;13503038;y?
> http://info.appdynamics.com/FreeJavaPerformanceDownload.html
> _______________________________________________
> tmux-users mailing list
> tmux-users@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/tmux-users

------------------------------------------------------------------------------
Don't let slow site performance ruin your business. Deploy New Relic APM
Deploy New Relic app performance management and know exactly
what is happening inside your Ruby, Python, PHP, Java, and .NET app
Try New Relic at no cost today and get our sweet Data Nerd shirt too!
http://p.sf.net/sfu/newrelic-dev2dev
_______________________________________________
tmux-users mailing list
tmux-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tmux-users

Reply via email to