summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mode-key.c525
-rw-r--r--tmux.h13
-rw-r--r--window-choose.c219
3 files changed, 497 insertions, 260 deletions
diff --git a/mode-key.c b/mode-key.c
index ea43962b..a505ff41 100644
--- a/mode-key.c
+++ b/mode-key.c
@@ -83,6 +83,9 @@ const struct mode_key_cmdstr mode_key_cmdstr_choice[] = {
{ 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_cmdstr_copy[] = {
/* 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 },
-
- { 0, -1, 0 }
+ { '\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 }
};
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, -1, 0 }
+ { '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 }
};
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, -1, 0 }
+ { ' ', 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 }
};
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 },
-
- { 0, -1, 0 }
+ { '\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 }
};
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, -1, 0 }
+ { '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 }
};
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, -1, 0 }
+ { ' ', 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 }
};
struct mode_key_tree mode_key_tree_emacs_copy;
diff --git a/tmux.h b/tmux.h
index 1fbad94b..e5ad1718 100644
--- a/tmux.h
+++ b/tmux.h
@@ -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. */
diff --git a/window-choose.c b/window-choose.c
index 7bab2ffe..55f95de7 100644
--- a/window-choose.c
+++ b/window-choose.c
@@ -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, 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 +115,9 @@ window_choose_ready(struct window_pane *wp, u_int cur,
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 *wp)
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 *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 *wp)
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_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->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, 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 +459,37 @@ 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_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_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 +897,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);