mirror of
https://github.com/tmux/tmux.git
synced 2026-06-20 17:25:57 +00:00
Merged master into floating_panes
This commit is contained in:
329
CHANGES
329
CHANGES
@@ -1,3 +1,332 @@
|
||||
CHANGES FROM 3.6b TO 3.7
|
||||
|
||||
* Add floating panes. These are panes which sit above the layout ("tiled
|
||||
panes") like popups but unlike popups are not modal and behave like panes (so
|
||||
the same escape sequence support). Floating panes are created with the
|
||||
new-pane command, bound to * by default.
|
||||
|
||||
Currently floating panes can only be moved and resized using the mouse. The
|
||||
default second status line (if status-format is set to 2) has changed to show
|
||||
a list of panes. Many obvious features are not yet available for floating
|
||||
panes (notably the ability to swap floating panes, resize them using
|
||||
resize-pane, change them between floating and tiles, and restore custom
|
||||
layouts with floating panes).
|
||||
|
||||
Mostly written by Michael Grant with help from Dane Jensen; testing and fixes
|
||||
from others.
|
||||
|
||||
* Allow run-shell arguments after a shell command to be expanded as #{1}, #{2}
|
||||
and so on (from Rasmus Thystrup Karstensen in issue 5121).
|
||||
|
||||
* Add -g to kill-session to kill all sessions in a session group (issue 5157
|
||||
from github at jiku dot jp).
|
||||
|
||||
* Tighten up read-only checks on attach-session, detach-client and
|
||||
switch-client so that a user should be able to only detach their own client
|
||||
(reported by John Walker).
|
||||
|
||||
* Increase escape delay if the buffer contains a partial paste end, fixes
|
||||
issues with at least Windows Terminal (from jing dot empty at gmail.com issue
|
||||
5088).
|
||||
|
||||
* When mode-keys is set to vi, do not allow the cursor to go into the invisible
|
||||
extra cell to the right of the visible text; this is closer to what vi(1)
|
||||
does (from Max Vim in issue 5070).
|
||||
|
||||
* Add a five second limit on pasting for terminals which mysteriously lose the
|
||||
end sequence if the paste is too big (that is, Terminal.app) (reported by
|
||||
Garri Djavadyan in issue 4527).
|
||||
|
||||
* Show file open errors more sensibly (reported by Meriel Luna Mittelbach in
|
||||
issue 5081).
|
||||
|
||||
* Update supported features list for Foot terminal (from Meriel Luna Mittelbach
|
||||
in issue 5079).
|
||||
|
||||
* Turn off the "is this a paste" guessing if the terminal supports bracket
|
||||
pasting instead (issue 5031).
|
||||
|
||||
* Check FIONREAD for all panes not just piped panes.
|
||||
|
||||
* Add emacs-style recentre-top-bottom command to copy mode (issue 5053 from
|
||||
sinyax75 at gmail dot com).
|
||||
|
||||
* Allow the indicator in tree mode to be customized by two new options:
|
||||
tree-mode-preview-format and tree-mode-preview-style.
|
||||
|
||||
* Fix control client hang on exit after toggling no-output (issue 5049 from
|
||||
Aaron Campbell). Also various other control mode fixes.
|
||||
|
||||
* Add support for line numbers in copy mode. There is a new
|
||||
copy-mode-line-numbers option which may be set to off, default (tmux's normal
|
||||
line numbering where 0 is the top visible line), absolute (first line in
|
||||
history is 1), relative (relative to the cursor) and hybrid (current line is
|
||||
absolute, others relative). Also adds copy-mode-line-number-style and
|
||||
copy-mode-current-line-number-style to set the style of the line numbers.
|
||||
When copy mode is entered with the mouse, line numbers stay off. From Leo
|
||||
Henon in issue 5025.
|
||||
|
||||
* Make C-[ have the same bindings as Escape for terminals with extended
|
||||
keys where they are different (issue 5035 from Eric Nicolas).
|
||||
|
||||
* Sanitize paste buffer names in paste_set and paste_rename (issue 5032 from
|
||||
Barrett Ruth).
|
||||
|
||||
* Do not hang in run-shell when job_run fails (from Barrett Ruth in issue
|
||||
5037).
|
||||
|
||||
* Add ability to forward progress bar to outside terminal (issue 4972
|
||||
from Eric Dorland).
|
||||
|
||||
* Translate keypad keys to text in prompt input (from Barrett Ruth in issue
|
||||
4996).
|
||||
|
||||
* Sanitize pane titles and window and session names more consistently and
|
||||
strictly, prevents C0 characters and other invisible characters causing
|
||||
problems (reported by Chris Monardo in issue 4999).
|
||||
|
||||
* Make clock visible on terminals without colours (from Manuel Einfalt in issue
|
||||
5001).
|
||||
|
||||
* Add detach to default session menu (suggested by Przemyslaw Sztoch).
|
||||
|
||||
* Include window format variables for pane notifications (issue 5007 from Saul
|
||||
Nogueras).
|
||||
|
||||
* Limit precision to 100 for formats to stop silly formats from running out of
|
||||
memory, reported by z1281552865 at gmail dot com. Also various other similar
|
||||
changes, mostly found by OSS-Fuzz.
|
||||
|
||||
* Add WAYLAND_DISPLAY to default update-environment (issue 4965). Also some
|
||||
additional XDG_* variables (issue 5169).
|
||||
|
||||
* Add -C flag to command-prompt to match display-message -C (do not freeze
|
||||
panes) (from Barrett Ruth in issue 4978).
|
||||
|
||||
* Cache user from getpwuid because it can be very expensive on some
|
||||
platforms (from Ben Maurer in issue 4973).
|
||||
|
||||
* Add remain-on-exit key to keep pane around until a key is pressed (from
|
||||
Michael Grant).
|
||||
|
||||
* Add some new mouse ranges called "control0" to "control9" and use to add some
|
||||
mouse controls to the pane state line (from Dane Jensen with some bits from
|
||||
Michael Grant).
|
||||
|
||||
* Handle OSC 9;4 progress bar sequence and store in format variables (from Eric
|
||||
Dorland in issue 4954).
|
||||
|
||||
* Correctly size buffer used for parsing clipboard sequences (from Michal
|
||||
Majchrowicz).
|
||||
|
||||
* Limit MSG_COMMAND argument to between 0 and 1000 to prevent a misbehaving
|
||||
client from crashing the server (from Michal Majchrowicz).
|
||||
|
||||
* Reorganize host keys are represented internally so they can be built more
|
||||
easily (from Dane Jensen in issue 4953).
|
||||
|
||||
* Add new fuzzers for command parsing, formats and styles (from David
|
||||
Korczynski in issue 4957). Also fix various issues shown from these.
|
||||
|
||||
* Add bracket_paste_flag format flag (from George Nachman in issue 4951).
|
||||
|
||||
* Use \- for hyphens in tmux.1 to cause newer groff versions to render them
|
||||
correctly (from Keith Thompson in issue 4948).
|
||||
|
||||
* Various minor code improvements and fixes from Pavel Lavrukhin (issue 4936
|
||||
and others).
|
||||
|
||||
* Use window options for cursor-style to avoid crash when no pane (from Arden
|
||||
Packeer in issue 4942).
|
||||
|
||||
* Fix issue where popup window gets overwritten by background updates (from
|
||||
Conor Taylor in issue 4920).
|
||||
|
||||
* Protect against overflow when scrollbar is off screen (from san65384 at gmail
|
||||
dot com in issue 4933).
|
||||
|
||||
* Copy hyperlinks when redrawing popup so they do not vanish (from Antoine
|
||||
Gaudreau Simard in issue 4925).
|
||||
|
||||
* Work around systemd killing panes early during system shutdown by creating
|
||||
dependencies from the panes to the service which started tmux (issue 4926
|
||||
from Dmitry Torokhov).
|
||||
|
||||
* Allow codepoint-widths to accept ranges (from san65384 at gmail dot com in
|
||||
issue 4930).
|
||||
|
||||
* Add a short builtin help text for each mode accessible with C-h (based on
|
||||
code from Patrick Motard in issue 4751).
|
||||
|
||||
* Draw message as one format, allowing prompts and messages to occupy only a
|
||||
portion of the status bar, overlaying the normal status content rather than
|
||||
replacing the entire line. A new message-format option now controls the
|
||||
entire message (like status-format). The message-style option now need to
|
||||
include "fill" in order to cover the whole width (the default has
|
||||
"fill=yellow"). From Conor Taylor in issue 4861.
|
||||
|
||||
* Add next/previous variables for windows in W: loop (from Conor Taylor in
|
||||
issue 4856).
|
||||
|
||||
* Various bug and memory leak fixes from Renaud Allard (issue 4916).
|
||||
|
||||
* Add pane_pipe_pid with pipe file descriptor.
|
||||
|
||||
* Make -c work with new-session -A (from Jody Frankowski in issue 4906).
|
||||
|
||||
* Allow copy mode to work for readonly clients, except for copy commands (from
|
||||
Dane Jensen).
|
||||
|
||||
* Pass paste buffer through vis(3) when pasting to prevent buffers containing
|
||||
for example the bracket end sequence causing issues, a new -S flag disables
|
||||
(reported by Mason Davis).
|
||||
|
||||
* Add sorting (-O flag) and a custom format (-F) to list-keys (from Dane Jensen
|
||||
in issue 4845).
|
||||
|
||||
* Add scroll-exit-on, scroll-exit-off, scroll-exit-toggle commands to copy mode
|
||||
(from xcdnlgd at hotmail dot com in issue 4884).
|
||||
|
||||
* Respond to DECRQM 2026 (from David Turnbull in issue 4887) and various others
|
||||
(from Ayman Bagabas in issue 5118).
|
||||
|
||||
* Fix various memory leaks reported by Huihui Huang (issue 4872).
|
||||
|
||||
* Pass which clipboard is set through to the terminal (from Axel Lindskog in
|
||||
issue 4858).
|
||||
|
||||
* Reuse extended entry when clearing RGB cell, to prevent memory growth when
|
||||
cells are repeatedly cleared (from Michael K Darling in issue 4862).
|
||||
|
||||
* Do not write before buffer when parsing empty clipboard or palette replies,
|
||||
or try to allocate zero bytes with an empty clipboard sequence (reported by
|
||||
DongHan Kim).
|
||||
|
||||
* Various bug fixes and code improvements from Conor Taylor (issue 4848).
|
||||
|
||||
* Clear search counts when clearing marks in case of repeated search (reported
|
||||
by Daniel Pereira in issue 4817).
|
||||
|
||||
* Make OSC 52 work in popups (from gogongxt at 163 dot com in issue 4797).
|
||||
|
||||
* Refresh copy mode when style changes (from Josh Cooper in issue 4830).
|
||||
|
||||
* Make sorting code common and add -O for sorting to the list commands (from
|
||||
Dane Jensen in issue 4813).
|
||||
|
||||
* Do not treat cells as empty unless the background colour stays the same,
|
||||
fixes invisible clock in clock mode (reported by Theo Buehler).
|
||||
|
||||
* When history-limit is changed, apply to existing panes, not just new
|
||||
ones (issue 4705).
|
||||
|
||||
* Reevaluate menu and popup styles on each draw to allow them to change when
|
||||
options change (from Josh Cooper in issues 4828 and 4829).
|
||||
|
||||
* Handle theme keys earlier so they are processed even if a popup is open (from
|
||||
Josh Cooper in issue 4827).
|
||||
|
||||
* Fix window-size=latest not resizing on switch-client in session groups (from
|
||||
Ilya Grigoriev in issue 4818).
|
||||
|
||||
* Add -e flag to command-prompt to close if empty (from Dane Jensen in issue
|
||||
4812).
|
||||
|
||||
* Correctly draw indicators when pane-border-indicators is set to both
|
||||
(reported by Ilya Grigoriev in issue 4780).
|
||||
|
||||
* Remember last pane or type of location for double and triple clicks and
|
||||
correctly handle it changes between first and second or second and third
|
||||
(issue 4795 from Shaobo Song).
|
||||
|
||||
* Add paste to the default pane menu (issue 4763).
|
||||
|
||||
* Reduce request timeout to 500 milliseconds to match the extended escape-time,
|
||||
and discard palette requests if receiving a reply for a different index.
|
||||
|
||||
* Extend escape timeout if there are active forwarded requests not just
|
||||
tmux's own requests (issue 4793).
|
||||
|
||||
* Correct redrawing of wide characters when overwritten (reported by Jake
|
||||
Stewart in issue 4737).
|
||||
|
||||
* If cannot find a terminator for palette responses, treat as a partial key not
|
||||
complete (issue 4749).
|
||||
|
||||
* Do not send theme unless it has changed, and do not send immediately when
|
||||
updates are enabled (issue 5787).
|
||||
|
||||
* Do not use ;;s in list-keys output as it is confusing and cannot be
|
||||
parsed on input (from Patrick Motard in issue 4750).
|
||||
|
||||
* Redraw pane borders when entering or leaving alternate screen (from Mike
|
||||
Jonkmans in issue 4788).
|
||||
|
||||
* Add focus-follows-mouse option (from Barry Wasdell in issue 4771).
|
||||
|
||||
* Add selection_mode format variable for copy mode (from Mike Jonkmans in issue
|
||||
4773).
|
||||
|
||||
* Add prompt-command-cursor-style (from Joshua Cooper in issue 4765).
|
||||
|
||||
* With status-keys vi, move the cursor left by one when pressing Escape to
|
||||
enter command mode, like vi (issue 4767 from Joshua Cooper).
|
||||
|
||||
* Add {current}/{active} for -t for current window or active pane (from Manuel
|
||||
Einfalt, issue 4766).
|
||||
|
||||
* Add support for applications to use synchronized output mode (DECSET 2026) to
|
||||
prevent screen tearing during rapid updates (from Chris Lloyd in issue 4744).
|
||||
|
||||
* Do not set a default prompt cursor colour because some terminals (urxvt, st)
|
||||
do not support the reset sequence (issue 4759).
|
||||
|
||||
* Add a scroll-to-mouse command for copy mode to scroll to the mouse position
|
||||
and bind to the scrollbar, brings the scrollbar keys into line with the other
|
||||
mouse keys (from Michael Grant in issue 4731).
|
||||
|
||||
* Bump the maximum number of SIXEL images to 20.
|
||||
|
||||
* Fix key code for M-BSpace (issue 4717).
|
||||
|
||||
* Fix calculation of scaled SIXEL size (from nincsnevem662 at gmail dot com in
|
||||
issue 4739). Also various other fixes and improvements for SIXEL.
|
||||
|
||||
* Fix a race between fork and pane_current_path, most noticeable on systems
|
||||
where starting processes is slow (issue 4719).
|
||||
|
||||
* Fix mouse position calculation on scrollbar with pane status line at the top
|
||||
(issue 4738 from Michael Grant).
|
||||
|
||||
* Do not read outside buffer if format is a single #, and do not loop forever
|
||||
if UTF-8 is unfinished in a format (reported by Giorgi Kobakhia in issue
|
||||
4735).
|
||||
|
||||
* Add a missing skin tone character (from Jake Stewart in issue 4736).
|
||||
|
||||
* Allow UTF-8 characters to be combined in either order (reported by Jake
|
||||
Stewart in issue 4726).
|
||||
|
||||
* Do not show scrollbar when entering copy mode from a pane in the alternate
|
||||
screen (issue 4728 from Michael Grant).
|
||||
|
||||
* Fix the size calculation for left-right windows used to spread out cells
|
||||
horizontally evenly (from Michael Grant in issue 4724).
|
||||
|
||||
* Add a get-clipboard option which when enabled (the default is off) and a
|
||||
clipboard is requested from a pane, requests it from the terminal and
|
||||
forwards to the requesting pane; also remove the now-redundant
|
||||
forward-to-pane ability from "refresh-client -l" (issue 4275).
|
||||
|
||||
* Fix the noattr attribute in styles, used by the default mode-style (issue
|
||||
4713).
|
||||
|
||||
* Do not remove TERM for commands run from config file (regression reported by
|
||||
Dennis Eriksen).
|
||||
|
||||
* Add seconds options for clock mode (from augustus7613 dot mail at pm dot me,
|
||||
issue 4697; later improved by Joao Pedro in issue 4760).
|
||||
|
||||
CHANGES FROM 3.6a TO 3.6b
|
||||
|
||||
* Remove images from the correct list when they are removed while in the
|
||||
|
||||
@@ -29,18 +29,21 @@
|
||||
|
||||
static enum cmd_retval cmd_capture_pane_exec(struct cmd *, struct cmdq_item *);
|
||||
|
||||
static char *cmd_capture_pane_append(char *, size_t *, char *, size_t);
|
||||
static char *cmd_capture_pane_append(char *, size_t *, const char *,
|
||||
size_t);
|
||||
static char *cmd_capture_pane_pending(struct args *, struct window_pane *,
|
||||
size_t *);
|
||||
static char *cmd_capture_pane_history(struct args *, struct cmdq_item *,
|
||||
struct window_pane *, size_t *);
|
||||
static char *cmd_capture_pane_hyperlinks(struct grid *, struct screen *,
|
||||
u_int, u_int *, u_int *, size_t *);
|
||||
|
||||
const struct cmd_entry cmd_capture_pane_entry = {
|
||||
.name = "capture-pane",
|
||||
.alias = "capturep",
|
||||
|
||||
.args = { "ab:CeE:JMNpPqS:Tt:", 0, 0, NULL },
|
||||
.usage = "[-aCeJMNpPqT] " CMD_BUFFER_USAGE " [-E end-line] "
|
||||
.args = { "ab:CeE:FHJLMNpPqS:Tt:", 0, 0, NULL },
|
||||
.usage = "[-aCeFHJLMNpPqT] " CMD_BUFFER_USAGE " [-E end-line] "
|
||||
"[-S start-line] " CMD_TARGET_PANE_USAGE,
|
||||
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
@@ -63,7 +66,8 @@ const struct cmd_entry cmd_clear_history_entry = {
|
||||
};
|
||||
|
||||
static char *
|
||||
cmd_capture_pane_append(char *buf, size_t *len, char *line, size_t linelen)
|
||||
cmd_capture_pane_append(char *buf, size_t *len, const char *line,
|
||||
size_t linelen)
|
||||
{
|
||||
buf = xrealloc(buf, *len + linelen + 1);
|
||||
memcpy(buf + *len, line, linelen);
|
||||
@@ -103,6 +107,46 @@ cmd_capture_pane_pending(struct args *args, struct window_pane *wp,
|
||||
return (buf);
|
||||
}
|
||||
|
||||
static char *
|
||||
cmd_capture_pane_hyperlinks(struct grid *gd, struct screen *s, u_int py,
|
||||
u_int *links, u_int *nlinks, size_t *len)
|
||||
{
|
||||
const struct grid_line *gl = grid_peek_line(gd, py);
|
||||
struct grid_cell gc;
|
||||
const char *uri;
|
||||
char *line = xstrdup("");
|
||||
u_int i, j;
|
||||
|
||||
*len = 0;
|
||||
|
||||
if (s->hyperlinks == NULL || (~gl->flags & GRID_LINE_HYPERLINK))
|
||||
return (line);
|
||||
|
||||
for (i = 0; i < gl->cellused; i++) {
|
||||
grid_get_cell(gd, i, py, &gc);
|
||||
if (gc.link == 0)
|
||||
continue;
|
||||
for (j = 0; j < *nlinks; j++) {
|
||||
if (links[j] == gc.link)
|
||||
break;
|
||||
}
|
||||
if (j != *nlinks)
|
||||
continue;
|
||||
|
||||
if (!hyperlinks_get(s->hyperlinks, gc.link, &uri, NULL, NULL))
|
||||
continue;
|
||||
|
||||
if (*nlinks == gd->sx)
|
||||
break;
|
||||
links[(*nlinks)++] = gc.link;
|
||||
|
||||
if (*len != 0)
|
||||
line = cmd_capture_pane_append(line, len, " ", 1);
|
||||
line = cmd_capture_pane_append(line, len, uri, strlen(uri));
|
||||
}
|
||||
return (line);
|
||||
}
|
||||
|
||||
static char *
|
||||
cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
|
||||
struct window_pane *wp, size_t *len)
|
||||
@@ -112,9 +156,11 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
|
||||
struct screen *s;
|
||||
struct grid_cell *gc = NULL;
|
||||
struct window_mode_entry *wme;
|
||||
int n, join_lines, flags = 0;
|
||||
int n, join_lines, number_lines, flags = 0;
|
||||
int show_flags, hyperlinks;
|
||||
u_int *links = NULL, nlinks = 0;
|
||||
u_int i, sx, top, bottom, tmp;
|
||||
char *cause, *buf, *line;
|
||||
char *cause, *buf = NULL, *line, b[64], *cp;
|
||||
const char *Sflag, *Eflag;
|
||||
size_t linelen;
|
||||
|
||||
@@ -152,7 +198,7 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
|
||||
if (cause != NULL) {
|
||||
top = gd->hsize;
|
||||
free(cause);
|
||||
} else if (n < 0 && (u_int) -n > gd->hsize)
|
||||
} else if (n < 0 && (u_int)-n > gd->hsize)
|
||||
top = 0;
|
||||
else
|
||||
top = gd->hsize + n;
|
||||
@@ -169,7 +215,7 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
|
||||
if (cause != NULL) {
|
||||
bottom = gd->hsize + gd->sy - 1;
|
||||
free(cause);
|
||||
} else if (n < 0 && (u_int) -n > gd->hsize)
|
||||
} else if (n < 0 && (u_int)-n > gd->hsize)
|
||||
bottom = 0;
|
||||
else
|
||||
bottom = gd->hsize + n;
|
||||
@@ -192,12 +238,57 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
|
||||
flags |= GRID_STRING_EMPTY_CELLS;
|
||||
if (!join_lines && !args_has(args, 'N'))
|
||||
flags |= GRID_STRING_TRIM_SPACES;
|
||||
number_lines = args_has(args, 'L');
|
||||
show_flags = args_has(args, 'F');
|
||||
hyperlinks = args_has(args, 'H');
|
||||
if (hyperlinks)
|
||||
links = xreallocarray(NULL, gd->sx, sizeof *links);
|
||||
|
||||
buf = NULL;
|
||||
for (i = top; i <= bottom; i++) {
|
||||
line = grid_string_cells(gd, 0, i, sx, &gc, flags, s);
|
||||
linelen = strlen(line);
|
||||
if (hyperlinks) {
|
||||
line = cmd_capture_pane_hyperlinks(gd, s, i, links,
|
||||
&nlinks, &linelen);
|
||||
} else {
|
||||
line = grid_string_cells(gd, 0, i, sx, &gc, flags, s);
|
||||
linelen = strlen(line);
|
||||
}
|
||||
if (hyperlinks && linelen == 0) {
|
||||
free(line);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (number_lines) {
|
||||
if (i >= gd->hsize)
|
||||
n = i - gd->hsize;
|
||||
else
|
||||
n = (int)i - (int)gd->hsize;
|
||||
n = snprintf(b, sizeof b, "%d ", n);
|
||||
if (n >= 0)
|
||||
buf = cmd_capture_pane_append(buf, len, b, n);
|
||||
}
|
||||
if (show_flags) {
|
||||
cp = b;
|
||||
*cp = '\0';
|
||||
|
||||
gl = grid_peek_line(gd, i);
|
||||
if (gl->flags & GRID_LINE_DEAD)
|
||||
*cp++ = 'D';
|
||||
if (gl->flags & GRID_LINE_HYPERLINK)
|
||||
*cp++ = 'H';
|
||||
if (gl->flags & GRID_LINE_START_OUTPUT)
|
||||
*cp++ = 'O';
|
||||
if (gl->flags & GRID_LINE_START_PROMPT)
|
||||
*cp++ = 'P';
|
||||
if (gl->flags & GRID_LINE_WRAPPED)
|
||||
*cp++ = 'W';
|
||||
if (gl->flags & GRID_LINE_EXTENDED)
|
||||
*cp++ = 'X';
|
||||
if (b == cp)
|
||||
*cp++ = '-';
|
||||
*cp++ = ' ';
|
||||
*cp = '\0';
|
||||
buf = cmd_capture_pane_append(buf, len, b, strlen (b));
|
||||
}
|
||||
buf = cmd_capture_pane_append(buf, len, line, linelen);
|
||||
|
||||
gl = grid_peek_line(gd, i);
|
||||
@@ -206,6 +297,9 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
|
||||
|
||||
free(line);
|
||||
}
|
||||
free(links);
|
||||
if (buf == NULL)
|
||||
buf = xstrdup("");
|
||||
return (buf);
|
||||
}
|
||||
|
||||
@@ -228,7 +322,7 @@ cmd_capture_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||
}
|
||||
|
||||
len = 0;
|
||||
if (args_has(args, 'P'))
|
||||
if (args_has(args, 'P') && !args_has(args, 'H'))
|
||||
buf = cmd_capture_pane_pending(args, wp, &len);
|
||||
else
|
||||
buf = cmd_capture_pane_history(args, item, wp, &len);
|
||||
|
||||
@@ -33,8 +33,8 @@ const struct cmd_entry cmd_choose_tree_entry = {
|
||||
.name = "choose-tree",
|
||||
.alias = NULL,
|
||||
|
||||
.args = { "F:f:GK:NO:rst:wyZ", 0, 1, cmd_choose_tree_args_parse },
|
||||
.usage = "[-GNrswZ] [-F format] [-f filter] [-K key-format] "
|
||||
.args = { "F:f:GhK:kNO:rst:wyZ", 0, 1, cmd_choose_tree_args_parse },
|
||||
.usage = "[-GhkNrswZ] [-F format] [-f filter] [-K key-format] "
|
||||
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
|
||||
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
@@ -47,8 +47,8 @@ const struct cmd_entry cmd_choose_client_entry = {
|
||||
.name = "choose-client",
|
||||
.alias = NULL,
|
||||
|
||||
.args = { "F:f:K:NO:rt:yZ", 0, 1, cmd_choose_tree_args_parse },
|
||||
.usage = "[-NrZ] [-F format] [-f filter] [-K key-format] "
|
||||
.args = { "F:f:hK:kNO:rt:yZ", 0, 1, cmd_choose_tree_args_parse },
|
||||
.usage = "[-hkNrZ] [-F format] [-f filter] [-K key-format] "
|
||||
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
|
||||
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
@@ -61,8 +61,8 @@ const struct cmd_entry cmd_choose_buffer_entry = {
|
||||
.name = "choose-buffer",
|
||||
.alias = NULL,
|
||||
|
||||
.args = { "F:f:K:NO:rt:yZ", 0, 1, cmd_choose_tree_args_parse },
|
||||
.usage = "[-NrZ] [-F format] [-f filter] [-K key-format] "
|
||||
.args = { "F:f:K:kNO:rt:yZ", 0, 1, cmd_choose_tree_args_parse },
|
||||
.usage = "[-kNrZ] [-F format] [-f filter] [-K key-format] "
|
||||
"[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
|
||||
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
@@ -75,8 +75,8 @@ const struct cmd_entry cmd_customize_mode_entry = {
|
||||
.name = "customize-mode",
|
||||
.alias = NULL,
|
||||
|
||||
.args = { "F:f:Nt:yZ", 0, 0, NULL },
|
||||
.usage = "[-NZ] [-F format] [-f filter] " CMD_TARGET_PANE_USAGE,
|
||||
.args = { "F:f:kNt:yZ", 0, 0, NULL },
|
||||
.usage = "[-kNZ] [-F format] [-f filter] " CMD_TARGET_PANE_USAGE,
|
||||
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
|
||||
|
||||
@@ -76,6 +76,40 @@ cmd_display_panes_put(struct screen_redraw_ctx *ctx,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_display_panes_draw_format(struct screen_redraw_ctx *ctx,
|
||||
struct window_pane *wp, u_int xoff, u_int yoff, u_int sx,
|
||||
const struct grid_cell *gc)
|
||||
{
|
||||
struct client *c = ctx->c;
|
||||
struct tty *tty = &c->tty;
|
||||
struct session *s = c->session;
|
||||
struct screen screen;
|
||||
struct screen_write_ctx sctx;
|
||||
struct visible_ranges *r;
|
||||
struct visible_range *ri;
|
||||
const char *format;
|
||||
char *expanded;
|
||||
u_int i, px = ctx->ox + xoff;
|
||||
|
||||
format = options_get_string(s->options, "display-panes-format");
|
||||
expanded = format_single(NULL, format, c, s, s->curw, wp);
|
||||
|
||||
screen_init(&screen, sx, 1, 0);
|
||||
screen_write_start(&sctx, &screen);
|
||||
format_draw(&sctx, gc, sx, expanded, NULL, 0);
|
||||
screen_write_stop(&sctx);
|
||||
free(expanded);
|
||||
|
||||
r = screen_redraw_get_visible_ranges(wp, px, wp->yoff, sx, NULL);
|
||||
for (i = 0; i < r->used; i++) {
|
||||
ri = &r->ranges[i];
|
||||
tty_draw_line(tty, &screen, ri->px - px, 0, ri->nx,
|
||||
ri->px - ctx->ox, yoff, gc, NULL);
|
||||
}
|
||||
screen_free(&screen);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
|
||||
struct window_pane *wp)
|
||||
@@ -89,8 +123,8 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
|
||||
u_int pane, idx, px, py, i, j, xoff, yoff, sx, sy;
|
||||
u_int cx, cy;
|
||||
int colour, active_colour;
|
||||
char buf[16], lbuf[16], rbuf[16], *ptr;
|
||||
size_t len, llen, rlen;
|
||||
char buf[16], lbuf[16], *ptr;
|
||||
size_t len, llen;
|
||||
|
||||
if (wp->xoff + (int)wp->sx <= ctx->ox ||
|
||||
wp->xoff >= ctx->ox + (int)ctx->sx ||
|
||||
@@ -159,7 +193,6 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
|
||||
bgc.bg = colour;
|
||||
}
|
||||
|
||||
rlen = xsnprintf(rbuf, sizeof rbuf, "%ux%u", wp->sx, wp->sy);
|
||||
if (pane > 9 && pane < 35)
|
||||
llen = xsnprintf(lbuf, sizeof lbuf, "%c", 'a' + (pane - 10));
|
||||
else
|
||||
@@ -207,13 +240,9 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
|
||||
|
||||
if (sy <= 6)
|
||||
goto out;
|
||||
tty_attributes(tty, &fgc, &grid_default_cell, NULL, NULL);
|
||||
if (rlen != 0 && sx >= rlen) {
|
||||
cx = xoff + sx - rlen;
|
||||
cy = yoff;
|
||||
cmd_display_panes_put(ctx, wp, cx, cy, rbuf, rlen);
|
||||
}
|
||||
cmd_display_panes_draw_format(ctx, wp, xoff, yoff, sx, &fgc);
|
||||
if (llen != 0) {
|
||||
tty_attributes(tty, &fgc, &grid_default_cell, NULL, NULL);
|
||||
cx = xoff + sx / 2 + len * 3 - llen - 1;
|
||||
cy = yoff + py + 5;
|
||||
cmd_display_panes_put(ctx, wp, cx, cy, lbuf, llen);
|
||||
|
||||
@@ -93,7 +93,7 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||
|
||||
lc = layout_get_tiled_cell(item, args, dst_w, dst_wp, flags, &cause);
|
||||
if (cause != NULL) {
|
||||
cmdq_error(item, "%s", cause);
|
||||
cmdq_error(item, "size or position %s", cause);
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
@@ -33,8 +33,8 @@ const struct cmd_entry cmd_kill_session_entry = {
|
||||
.name = "kill-session",
|
||||
.alias = NULL,
|
||||
|
||||
.args = { "aCt:", 0, 0, NULL },
|
||||
.usage = "[-aC] " CMD_TARGET_SESSION_USAGE,
|
||||
.args = { "aCgt:", 0, 0, NULL },
|
||||
.usage = "[-aCg] " CMD_TARGET_SESSION_USAGE,
|
||||
|
||||
.target = { 't', CMD_FIND_SESSION, 0 },
|
||||
|
||||
@@ -48,6 +48,7 @@ cmd_kill_session_exec(struct cmd *self, struct cmdq_item *item)
|
||||
struct args *args = cmd_get_args(self);
|
||||
struct cmd_find_state *target = cmdq_get_target(item);
|
||||
struct session *s = target->s, *sloop, *stmp;
|
||||
struct session_group *sg;
|
||||
struct winlink *wl;
|
||||
|
||||
if (args_has(args, 'C')) {
|
||||
@@ -63,6 +64,12 @@ cmd_kill_session_exec(struct cmd *self, struct cmdq_item *item)
|
||||
session_destroy(sloop, 1, __func__);
|
||||
}
|
||||
}
|
||||
} else if (args_has(args, 'g') &&
|
||||
(sg = session_group_contains(s)) != NULL) {
|
||||
TAILQ_FOREACH_SAFE(sloop, &sg->sessions, gentry, stmp) {
|
||||
server_destroy_session(sloop);
|
||||
session_destroy(sloop, 1, __func__);
|
||||
}
|
||||
} else {
|
||||
server_destroy_session(s);
|
||||
session_destroy(s, 1, __func__);
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
"," \
|
||||
"bind-key #{?key_has_repeat,#{?key_repeat,-r, },} " \
|
||||
"-T #{p|#{key_table_width}:key_table} " \
|
||||
"#{p|#{key_string_width}:key_string} " \
|
||||
"#{p|#{key_string_width}:#{q|a:key_string}} " \
|
||||
"#{key_command}}"
|
||||
|
||||
static enum cmd_retval cmd_list_keys_exec(struct cmd *, struct cmdq_item *);
|
||||
|
||||
@@ -38,11 +38,11 @@ const struct cmd_entry cmd_new_pane_entry = {
|
||||
.name = "new-pane",
|
||||
.alias = "newp",
|
||||
|
||||
.args = { "bc:de:fF:hIkl:Lm:p:PR:s:S:t:vx:X:y:Y:Z", 0, -1, NULL },
|
||||
.args = { "bc:de:EfF:hIkl:Lm:p:PR:s:S:t:T:vx:X:y:Y:Z", 0, -1, NULL },
|
||||
.usage = "[-bdefhIklPvZ] [-c start-directory] [-e environment] "
|
||||
"[-F format] [-l size] [-m message] [-p percentage] "
|
||||
"[-s style] [-S active-border-style] "
|
||||
"[-R inactive-border-style] [-x width] [-y height] "
|
||||
"[-R inactive-border-style] [-T title] [-x width] [-y height] "
|
||||
"[-X x-position] [-Y y-position] " CMD_TARGET_PANE_USAGE " "
|
||||
"[shell-command [argument ...]]",
|
||||
|
||||
@@ -56,11 +56,11 @@ const struct cmd_entry cmd_split_window_entry = {
|
||||
.name = "split-window",
|
||||
.alias = "splitw",
|
||||
|
||||
.args = { "bc:de:fF:hIkl:m:p:PR:s:S:t:vZ", 0, -1, NULL },
|
||||
.args = { "bc:de:EfF:hIkl:m:p:PR:s:S:t:T:vZ", 0, -1, NULL },
|
||||
.usage = "[-bdefhIklPvZ] [-c start-directory] [-e environment] "
|
||||
"[-F format] [-l size] [-m message] [-p percentage] "
|
||||
"[-s style] [-S active-border-style] "
|
||||
"[-R inactive-border-style] " CMD_TARGET_PANE_USAGE " "
|
||||
"[-R inactive-border-style] [-T title] " CMD_TARGET_PANE_USAGE " "
|
||||
"[shell-command [argument ...]]",
|
||||
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
@@ -83,9 +83,9 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||
struct window_pane *wp = target->wp, *new_wp;
|
||||
struct layout_cell *lc = NULL;
|
||||
struct cmd_find_state fs;
|
||||
int input, is_floating, flags = 0;
|
||||
int input, empty, is_floating, flags = 0;
|
||||
const char *template, *style;
|
||||
char *cause = NULL, *cp;
|
||||
char *cause = NULL, *cp, *title;
|
||||
struct args_value *av;
|
||||
u_int count = args_count(args);
|
||||
|
||||
@@ -93,22 +93,33 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||
is_floating = !args_has(args, 'L');
|
||||
else
|
||||
is_floating = 0;
|
||||
input = (args_has(args, 'I') && count == 0);
|
||||
|
||||
flags = is_floating ? SPAWN_FLOATING : 0;
|
||||
if (args_has(args, 'b'))
|
||||
flags |= SPAWN_BEFORE;
|
||||
if (args_has(args, 'f'))
|
||||
flags |= SPAWN_FULLSIZE;
|
||||
if (input || (count == 1 && *args_string(args, 0) == '\0'))
|
||||
|
||||
input = args_has(args, 'I');
|
||||
if (input)
|
||||
empty = 1;
|
||||
else
|
||||
empty = args_has(args, 'E');
|
||||
if (empty &&
|
||||
count != 0 &&
|
||||
(count != 1 || *args_string(args, 0) != '\0')) {
|
||||
cmdq_error(item, "command cannot be given for empty pane");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
if (empty)
|
||||
flags |= SPAWN_EMPTY;
|
||||
|
||||
if (is_floating)
|
||||
lc = layout_get_floating_cell(item, args, w, wp, lc, &cause);
|
||||
lc = layout_get_floating_cell(item, args, w, wp, &cause);
|
||||
else
|
||||
lc = layout_get_tiled_cell(item, args, w, wp, flags, &cause);
|
||||
if (cause != NULL) {
|
||||
cmdq_error(item, "%s", cause);
|
||||
cmdq_error(item, "size or position %s", cause);
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
@@ -183,6 +194,12 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||
"remain-on-exit-format",
|
||||
0, "%s", args_get(args, 'm'));
|
||||
}
|
||||
if (args_has(args, 'T')) {
|
||||
title = format_single_from_target(item, args_get(args, 'T'));
|
||||
screen_set_title(&new_wp->base, title);
|
||||
notify_pane("pane-title-changed", new_wp);
|
||||
free(title);
|
||||
}
|
||||
|
||||
if (input) {
|
||||
switch (window_pane_start_input(new_wp, item, &cause)) {
|
||||
@@ -209,7 +226,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||
window_pop_zoom(wp->window);
|
||||
server_redraw_window(wp->window);
|
||||
}
|
||||
server_status_session(s);
|
||||
server_redraw_session(s);
|
||||
|
||||
if (args_has(args, 'P')) {
|
||||
if ((template = args_get(args, 'F')) == NULL)
|
||||
|
||||
@@ -79,7 +79,7 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||
if (src_wp == dst_wp)
|
||||
goto out;
|
||||
|
||||
if (window_pane_is_floating(src_wp) &&
|
||||
if (window_pane_is_floating(src_wp) ||
|
||||
window_pane_is_floating(dst_wp)) {
|
||||
cmdq_error(item, "cannot swap floating panes");
|
||||
return (CMD_RETURN_ERROR);
|
||||
|
||||
59
format.c
59
format.c
@@ -116,6 +116,8 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2)
|
||||
#define FORMAT_NOT 0x80000
|
||||
#define FORMAT_NOT_NOT 0x100000
|
||||
#define FORMAT_REPEAT 0x200000
|
||||
#define FORMAT_QUOTE_ARGUMENTS 0x400000
|
||||
#define FORMAT_RELATIVE 0x800000
|
||||
|
||||
/* Limit on recursion. */
|
||||
#define FORMAT_LOOP_LIMIT 100
|
||||
@@ -4079,6 +4081,50 @@ format_pretty_time(time_t t, int seconds)
|
||||
return (xstrdup(s));
|
||||
}
|
||||
|
||||
/* Make a relative time. */
|
||||
static char *
|
||||
format_relative_time(time_t t)
|
||||
{
|
||||
time_t now, age;
|
||||
u_int d, h, m, s;
|
||||
char out[32], sign;
|
||||
|
||||
time(&now);
|
||||
if (t == now)
|
||||
return (xstrdup("0s"));
|
||||
if (t > now) {
|
||||
sign = '+';
|
||||
age = t - now;
|
||||
} else {
|
||||
sign = '-';
|
||||
age = now - t;
|
||||
}
|
||||
|
||||
d = age / 86400;
|
||||
h = (age % 86400) / 3600;
|
||||
m = (age % 3600) / 60;
|
||||
s = age % 60;
|
||||
|
||||
if (d != 0) {
|
||||
if (h != 0)
|
||||
xsnprintf(out, sizeof out, "%c%ud%uh", sign, d, h);
|
||||
else
|
||||
xsnprintf(out, sizeof out, "%c%ud", sign, d);
|
||||
} else if (h != 0) {
|
||||
if (m != 0)
|
||||
xsnprintf(out, sizeof out, "%c%uh%um", sign, h, m);
|
||||
else
|
||||
xsnprintf(out, sizeof out, "%c%uh", sign, h);
|
||||
} else if (m != 0) {
|
||||
if (s != 0)
|
||||
xsnprintf(out, sizeof out, "%c%um%us", sign, m, s);
|
||||
else
|
||||
xsnprintf(out, sizeof out, "%c%um", sign, m);
|
||||
} else
|
||||
xsnprintf(out, sizeof out, "%c%us", sign, s);
|
||||
return (xstrdup(out));
|
||||
}
|
||||
|
||||
/* Find a format entry. */
|
||||
static char *
|
||||
format_find(struct format_tree *ft, const char *key, int modifiers,
|
||||
@@ -4160,7 +4206,9 @@ found:
|
||||
}
|
||||
if (t == 0)
|
||||
return (NULL);
|
||||
if (modifiers & FORMAT_PRETTY)
|
||||
if (modifiers & FORMAT_RELATIVE)
|
||||
found = format_relative_time(t);
|
||||
else if (modifiers & FORMAT_PRETTY)
|
||||
found = format_pretty_time(t, 0);
|
||||
else {
|
||||
if (time_format != NULL) {
|
||||
@@ -4199,6 +4247,11 @@ found:
|
||||
found = format_quote_style(saved);
|
||||
free(saved);
|
||||
}
|
||||
if (modifiers & FORMAT_QUOTE_ARGUMENTS) {
|
||||
saved = found;
|
||||
found = args_escape(saved);
|
||||
free(saved);
|
||||
}
|
||||
return (found);
|
||||
}
|
||||
|
||||
@@ -5160,6 +5213,8 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
||||
break;
|
||||
if (strchr(fm->argv[0], 'p') != NULL)
|
||||
modifiers |= FORMAT_PRETTY;
|
||||
else if (strchr(fm->argv[0], 'r') != NULL)
|
||||
modifiers |= FORMAT_RELATIVE;
|
||||
else if (fm->argc >= 2 &&
|
||||
strchr(fm->argv[0], 'f') != NULL) {
|
||||
free(time_format);
|
||||
@@ -5172,6 +5227,8 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
||||
else if (strchr(fm->argv[0], 'e') != NULL ||
|
||||
strchr(fm->argv[0], 'h') != NULL)
|
||||
modifiers |= FORMAT_QUOTE_STYLE;
|
||||
else if (strchr(fm->argv[0], 'a') != NULL)
|
||||
modifiers |= FORMAT_QUOTE_ARGUMENTS;
|
||||
break;
|
||||
case 'E':
|
||||
modifiers |= FORMAT_EXPAND;
|
||||
|
||||
13
grid.c
13
grid.c
@@ -125,6 +125,8 @@ grid_extended_cell(struct grid_line *gl, struct grid_cell_entry *gce,
|
||||
else if (gce->offset >= gl->extdsize)
|
||||
fatalx("offset too big");
|
||||
gl->flags |= GRID_LINE_EXTENDED;
|
||||
if (gc->link != 0)
|
||||
gl->flags |= GRID_LINE_HYPERLINK;
|
||||
|
||||
if (gc->flags & GRID_FLAG_TAB)
|
||||
uc = gc->data.width;
|
||||
@@ -285,9 +287,8 @@ static void
|
||||
grid_free_line(struct grid *gd, u_int py)
|
||||
{
|
||||
free(gd->linedata[py].celldata);
|
||||
gd->linedata[py].celldata = NULL;
|
||||
free(gd->linedata[py].extddata);
|
||||
gd->linedata[py].extddata = NULL;
|
||||
memset(&gd->linedata[py], 0, sizeof gd->linedata[py]);
|
||||
}
|
||||
|
||||
/* Free several lines. */
|
||||
@@ -332,9 +333,7 @@ void
|
||||
grid_destroy(struct grid *gd)
|
||||
{
|
||||
grid_free_lines(gd, 0, gd->hsize + gd->sy);
|
||||
|
||||
free(gd->linedata);
|
||||
|
||||
free(gd);
|
||||
}
|
||||
|
||||
@@ -414,12 +413,14 @@ grid_collect_history(struct grid *gd, int all)
|
||||
void
|
||||
grid_remove_history(struct grid *gd, u_int ny)
|
||||
{
|
||||
u_int yy;
|
||||
u_int yy, start;
|
||||
|
||||
if (ny > gd->hsize)
|
||||
return;
|
||||
start = gd->hsize + gd->sy - ny;
|
||||
for (yy = 0; yy < ny; yy++)
|
||||
grid_free_line(gd, gd->hsize + gd->sy - 1 - yy);
|
||||
grid_free_line(gd, start + yy);
|
||||
memset(&gd->linedata[start], 0, ny * sizeof *gd->linedata);
|
||||
gd->hsize -= ny;
|
||||
}
|
||||
|
||||
|
||||
160
layout.c
160
layout.c
@@ -46,9 +46,6 @@ static int layout_set_size_check(struct window *, struct layout_cell *,
|
||||
enum layout_type, int);
|
||||
static void layout_resize_child_cells(struct window *,
|
||||
struct layout_cell *);
|
||||
static struct layout_cell *layout_active_neighbour(struct layout_cell *, int);
|
||||
void layout_redistribute_cells(struct window *, struct layout_cell *,
|
||||
enum layout_type);
|
||||
|
||||
/* Create a new layout cell. */
|
||||
struct layout_cell *
|
||||
@@ -253,9 +250,10 @@ layout_fix_offsets1(struct layout_cell *lc)
|
||||
if (lc->type == LAYOUT_LEFTRIGHT) {
|
||||
xoff = lc->xoff;
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||
if (lcchild->type == LAYOUT_WINDOWPANE &&
|
||||
if (lcchild->flags & LAYOUT_CELL_FLOATING ||
|
||||
(lcchild->type == LAYOUT_WINDOWPANE &&
|
||||
lcchild->wp != NULL &&
|
||||
lcchild->wp->flags & PANE_HIDDEN)
|
||||
(lcchild->wp->flags & PANE_HIDDEN)))
|
||||
continue;
|
||||
lcchild->xoff = xoff;
|
||||
lcchild->yoff = lc->yoff;
|
||||
@@ -266,9 +264,10 @@ layout_fix_offsets1(struct layout_cell *lc)
|
||||
} else {
|
||||
yoff = lc->yoff;
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||
if (lcchild->type == LAYOUT_WINDOWPANE &&
|
||||
if (lcchild->flags & LAYOUT_CELL_FLOATING ||
|
||||
(lcchild->type == LAYOUT_WINDOWPANE &&
|
||||
lcchild->wp != NULL &&
|
||||
lcchild->wp->flags & PANE_HIDDEN)
|
||||
(lcchild->wp->flags & PANE_HIDDEN)))
|
||||
continue;
|
||||
lcchild->xoff = lc->xoff;
|
||||
lcchild->yoff = yoff;
|
||||
@@ -285,6 +284,10 @@ layout_fix_offsets(struct window *w)
|
||||
{
|
||||
struct layout_cell *lc = w->layout_root;
|
||||
|
||||
/* Root consists of a single floating cell */
|
||||
if (lc->flags & LAYOUT_CELL_FLOATING)
|
||||
return;
|
||||
|
||||
lc->xoff = 0;
|
||||
lc->yoff = 0;
|
||||
|
||||
@@ -493,8 +496,11 @@ layout_resize_adjust(struct window *w, struct layout_cell *lc,
|
||||
|
||||
/* Child cell runs in a different direction. */
|
||||
if (lc->type != type) {
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry)
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||
if (lcchild->flags & LAYOUT_CELL_FLOATING)
|
||||
continue;
|
||||
layout_resize_adjust(w, lcchild, type, change);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -506,6 +512,8 @@ layout_resize_adjust(struct window *w, struct layout_cell *lc,
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||
if (change == 0)
|
||||
break;
|
||||
if (lcchild->flags & LAYOUT_CELL_FLOATING)
|
||||
continue;
|
||||
if (change > 0) {
|
||||
layout_resize_adjust(w, lcchild, type, 1);
|
||||
change--;
|
||||
@@ -610,30 +618,33 @@ void
|
||||
layout_destroy_cell(struct window *w, struct layout_cell *lc,
|
||||
struct layout_cell **lcroot)
|
||||
{
|
||||
struct layout_cell *lcother, *lcparent;
|
||||
struct layout_cell *lcother = NULL, *lcparent;
|
||||
|
||||
/*
|
||||
* If no parent, this is either a floating pane or the last
|
||||
* pane so window close is imminent and there is no need to
|
||||
* resize anything.
|
||||
*/
|
||||
/* If no parent, this is the last pane in a window. */
|
||||
lcparent = lc->parent;
|
||||
if (lcparent == NULL) {
|
||||
if (lc->wp != NULL && !window_pane_is_floating(lc->wp))
|
||||
if (lc->wp != NULL)
|
||||
*lcroot = NULL;
|
||||
layout_free_cell(lc);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Merge the space into the previous or next cell. */
|
||||
if (lc == TAILQ_FIRST(&lcparent->cells))
|
||||
lcother = TAILQ_NEXT(lc, entry);
|
||||
else
|
||||
lcother = TAILQ_PREV(lc, layout_cells, entry);
|
||||
if (lcother != NULL && lcparent->type == LAYOUT_LEFTRIGHT)
|
||||
layout_resize_adjust(w, lcother, lcparent->type, lc->sx + 1);
|
||||
else if (lcother != NULL)
|
||||
layout_resize_adjust(w, lcother, lcparent->type, lc->sy + 1);
|
||||
if (~lc->flags & LAYOUT_CELL_FLOATING) {
|
||||
/* Merge the space into the previous or next cell. */
|
||||
if (lc == TAILQ_FIRST(&lcparent->cells))
|
||||
lcother = TAILQ_NEXT(lc, entry);
|
||||
else
|
||||
lcother = TAILQ_PREV(lc, layout_cells, entry);
|
||||
}
|
||||
if (lcother != NULL && (~lcother->flags & LAYOUT_CELL_FLOATING)) {
|
||||
if (lcparent->type == LAYOUT_LEFTRIGHT) {
|
||||
layout_resize_adjust(w, lcother, lcparent->type,
|
||||
lc->sx + 1);
|
||||
} else {
|
||||
layout_resize_adjust(w, lcother, lcparent->type,
|
||||
lc->sy + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove this from the parent's list. */
|
||||
TAILQ_REMOVE(&lcparent->cells, lc, entry);
|
||||
@@ -649,8 +660,10 @@ layout_destroy_cell(struct window *w, struct layout_cell *lc,
|
||||
|
||||
lc->parent = lcparent->parent;
|
||||
if (lc->parent == NULL) {
|
||||
lc->xoff = 0;
|
||||
lc->yoff = 0;
|
||||
if (~lc->flags & LAYOUT_CELL_FLOATING) {
|
||||
lc->xoff = 0;
|
||||
lc->yoff = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the sole remaining child is a hidden
|
||||
@@ -774,6 +787,8 @@ layout_resize(struct window *w, u_int sx, u_int sy)
|
||||
* out proportionately - this should leave the layout fitting the new
|
||||
* window size.
|
||||
*/
|
||||
if (lc->type == LAYOUT_WINDOWPANE && (lc->flags & LAYOUT_CELL_FLOATING))
|
||||
return;
|
||||
xchange = sx - lc->sx;
|
||||
xlimit = layout_resize_check(w, lc, LAYOUT_LEFTRIGHT);
|
||||
if (xchange < 0 && xchange < -xlimit)
|
||||
@@ -1086,6 +1101,8 @@ layout_resize_child_cells(struct window *w, struct layout_cell *lc)
|
||||
count = 0;
|
||||
previous = 0;
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||
if (lcchild->flags & LAYOUT_CELL_FLOATING)
|
||||
continue;
|
||||
count++;
|
||||
if (lc->type == LAYOUT_LEFTRIGHT)
|
||||
previous += lcchild->sx;
|
||||
@@ -1104,6 +1121,8 @@ layout_resize_child_cells(struct window *w, struct layout_cell *lc)
|
||||
/* Resize children into the new size. */
|
||||
idx = 0;
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||
if (lcchild->flags & LAYOUT_CELL_FLOATING)
|
||||
continue;
|
||||
if (lc->type == LAYOUT_TOPBOTTOM) {
|
||||
lcchild->sx = lc->sx;
|
||||
lcchild->xoff = lc->xoff;
|
||||
@@ -1112,9 +1131,10 @@ layout_resize_child_cells(struct window *w, struct layout_cell *lc)
|
||||
lc->type, lc->sx, count - idx, available);
|
||||
available -= (lcchild->sx + 1);
|
||||
}
|
||||
if (lc->type == LAYOUT_LEFTRIGHT)
|
||||
if (lc->type == LAYOUT_LEFTRIGHT) {
|
||||
lcchild->sy = lc->sy;
|
||||
else {
|
||||
lcchild->yoff = lc->yoff;
|
||||
} else {
|
||||
lcchild->sy = layout_new_pane_size(w, previous, lcchild,
|
||||
lc->type, lc->sy, count - idx, available);
|
||||
available -= (lcchild->sy + 1);
|
||||
@@ -1303,6 +1323,39 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
|
||||
return (lcnew);
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a cell for a new floating pane. This must be followed by
|
||||
* layout_assign_pane before much else happens!
|
||||
*/
|
||||
struct layout_cell *
|
||||
layout_floating_pane(struct window *w, u_int sx, u_int sy, int ox, int oy)
|
||||
{
|
||||
struct layout_cell *lc = w->layout_root, *lcnew, *lcparent;
|
||||
|
||||
if (lc->type == LAYOUT_WINDOWPANE) {
|
||||
/*
|
||||
* Adding a pane to a root that doesn't have a container. Must
|
||||
* create and insert a new root.
|
||||
*/
|
||||
lcparent = layout_create_cell(NULL);
|
||||
layout_make_node(lcparent, LAYOUT_TOPBOTTOM);
|
||||
layout_set_size(lcparent, w->sx, w->sy, 0, 0);
|
||||
w->layout_root = lcparent;
|
||||
|
||||
/* Insert the old cell. */
|
||||
lc->parent = lcparent;
|
||||
TAILQ_INSERT_HEAD(&lcparent->cells, lc, entry);
|
||||
} else
|
||||
lcparent = w->layout_root;
|
||||
|
||||
lcnew = layout_create_cell(lcparent);
|
||||
TAILQ_INSERT_TAIL(&lcparent->cells, lcnew, entry);
|
||||
lcnew->flags |= LAYOUT_CELL_FLOATING;
|
||||
layout_set_size(lcnew, sx, sy, ox, oy);
|
||||
|
||||
return (lcnew);
|
||||
}
|
||||
|
||||
/* Destroy the cell associated with a pane. */
|
||||
void
|
||||
layout_close_pane(struct window_pane *wp)
|
||||
@@ -1314,6 +1367,7 @@ layout_close_pane(struct window_pane *wp)
|
||||
|
||||
/* Remove the cell. */
|
||||
layout_destroy_cell(w, wp->layout_cell, &w->layout_root);
|
||||
wp->layout_cell = NULL;
|
||||
|
||||
/* Fix pane offsets and sizes. */
|
||||
if (w->layout_root != NULL) {
|
||||
@@ -1470,49 +1524,37 @@ layout_get_tiled_cell(struct cmdq_item *item, struct args *args,
|
||||
/* Get a new floating cell. */
|
||||
struct layout_cell *
|
||||
layout_get_floating_cell(struct cmdq_item *item, struct args *args,
|
||||
struct window *w, __unused struct window_pane *wp, struct layout_cell *lc,
|
||||
char **cause)
|
||||
struct window *w, __unused struct window_pane *wp, char **cause)
|
||||
{
|
||||
u_int sx, sy, ox, oy;
|
||||
int new = 0;
|
||||
|
||||
if (lc == NULL) {
|
||||
lc = layout_create_cell(NULL);
|
||||
new = 1;
|
||||
}
|
||||
|
||||
sx = lc->sx; sy = lc->sy;
|
||||
ox = lc->xoff; oy = lc->yoff;
|
||||
struct layout_cell *lcnew;
|
||||
int sx = w->sx / 2, sy = w->sy / 4;
|
||||
int ox = INT_MAX, oy = INT_MAX;
|
||||
|
||||
if (args_has(args, 'x')) {
|
||||
sx = args_percentage_and_expand(args, 'x', 0, USHRT_MAX, w->sx,
|
||||
sx = args_percentage_and_expand(args, 'x', 0, w->sx - 1, w->sx,
|
||||
item, cause);
|
||||
if (*cause != NULL)
|
||||
goto error;
|
||||
return (NULL);
|
||||
}
|
||||
if (args_has(args, 'y')) {
|
||||
sy = args_percentage_and_expand(args, 'y', 0, USHRT_MAX, w->sy,
|
||||
sy = args_percentage_and_expand(args, 'y', 0, w->sy - 1, w->sy,
|
||||
item, cause);
|
||||
if (*cause != NULL)
|
||||
goto error;
|
||||
return (NULL);
|
||||
}
|
||||
if (args_has(args, 'X')) {
|
||||
ox = args_percentage_and_expand(args, 'X', 0, USHRT_MAX, w->sx,
|
||||
item, cause);
|
||||
ox = args_percentage_and_expand(args, 'X', -sx, w->sx,
|
||||
w->sx, item, cause);
|
||||
if (*cause != NULL)
|
||||
goto error;
|
||||
return (NULL);
|
||||
}
|
||||
if (args_has(args, 'Y')) {
|
||||
oy = args_percentage_and_expand(args, 'Y', 0, USHRT_MAX, w->sy,
|
||||
item, cause);
|
||||
oy = args_percentage_and_expand(args, 'Y', -sy, w->sy,
|
||||
w->sy, item, cause);
|
||||
if (*cause != NULL)
|
||||
goto error;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (sx == UINT_MAX)
|
||||
sx = w->sx / 2;
|
||||
if (sy == UINT_MAX)
|
||||
sy = w->sy / 4;
|
||||
if (ox == INT_MAX) {
|
||||
if (w->last_new_pane_x == 0)
|
||||
ox = 4;
|
||||
@@ -1533,13 +1575,7 @@ layout_get_floating_cell(struct cmdq_item *item, struct args *args,
|
||||
}
|
||||
w->last_new_pane_y = oy;
|
||||
}
|
||||
layout_set_size(lc, sx, sy, ox, oy);
|
||||
lc->flags |= LAYOUT_CELL_FLOATING;
|
||||
|
||||
return (lc);
|
||||
|
||||
error:
|
||||
if (new)
|
||||
layout_destroy_cell(w, lc, &w->layout_root);
|
||||
return (NULL);
|
||||
lcnew = layout_floating_pane(w, sx, sy, ox, oy);
|
||||
return (lcnew);
|
||||
}
|
||||
|
||||
@@ -1224,6 +1224,11 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
|
||||
u_int i, x, y;
|
||||
int choice, preview;
|
||||
|
||||
if (mtd->line_size == 0) {
|
||||
*key = KEYC_NONE;
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (KEYC_IS_MOUSE(*key) && m != NULL) {
|
||||
if (cmd_mouse_at(mtd->wp, m, &x, &y, 0) != 0) {
|
||||
*key = KEYC_NONE;
|
||||
|
||||
@@ -647,6 +647,14 @@ const struct options_table_entry options_table[] = {
|
||||
.text = "Colour of not active panes for 'display-panes'."
|
||||
},
|
||||
|
||||
{ .name = "display-panes-format",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SESSION,
|
||||
.default_str = "#[align=right]#{pane_width}x#{pane_height}",
|
||||
.text = "Format of text shown by 'display-panes', expanded for each "
|
||||
"pane."
|
||||
},
|
||||
|
||||
{ .name = "display-panes-time",
|
||||
.type = OPTIONS_TABLE_NUMBER,
|
||||
.scope = OPTIONS_TABLE_SESSION,
|
||||
@@ -1028,7 +1036,8 @@ const struct options_table_entry options_table[] = {
|
||||
.flags = OPTIONS_TABLE_IS_ARRAY,
|
||||
.default_str = "DISPLAY KRB5CCNAME MSYSTEM SSH_ASKPASS SSH_AUTH_SOCK "
|
||||
"SSH_AGENT_PID SSH_CONNECTION WAYLAND_DISPLAY "
|
||||
"WINDOWID XAUTHORITY",
|
||||
"WINDOWID XAUTHORITY XDG_CURRENT_DESKTOP "
|
||||
"XDG_SESSION_DESKTOP XDG_SESSION_TYPE",
|
||||
.text = "List of environment variables to update in the session "
|
||||
"environment when a client is attached."
|
||||
},
|
||||
|
||||
@@ -4,9 +4,9 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
TMUX2="$TEST_TMUX -Ltest2"
|
||||
TMUX2="$TEST_TMUX -Ltest2 -f/dev/null"
|
||||
$TMUX2 kill-server 2>/dev/null
|
||||
|
||||
TMP=$(mktemp)
|
||||
|
||||
@@ -11,9 +11,9 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
TMUX_OUTER="$TEST_TMUX -Ltest2"
|
||||
TMUX_OUTER="$TEST_TMUX -Ltest2 -f/dev/null"
|
||||
$TMUX_OUTER kill-server 2>/dev/null
|
||||
|
||||
trap "$TMUX kill-server 2>/dev/null; $TMUX_OUTER kill-server 2>/dev/null" 0 1 15
|
||||
|
||||
@@ -6,7 +6,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
TMP=$(mktemp)
|
||||
TMP2=$(mktemp)
|
||||
trap "rm -f $TMP $TMP2" 0 1 15
|
||||
|
||||
@@ -7,7 +7,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
TMP=$(mktemp)
|
||||
|
||||
@@ -4,7 +4,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
TMP=$(mktemp)
|
||||
|
||||
@@ -4,7 +4,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
TMP=$(mktemp)
|
||||
|
||||
@@ -4,7 +4,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
for i in conf/*.conf; do
|
||||
|
||||
@@ -4,7 +4,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
TMP=$(mktemp)
|
||||
|
||||
@@ -8,7 +8,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
TMP=$(mktemp)
|
||||
|
||||
@@ -4,7 +4,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -f/dev/null -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
$TMUX new -d -x40 -y10 \
|
||||
|
||||
@@ -34,14 +34,17 @@ $TMUX send-keys -X previous-word
|
||||
$TMUX send-keys -X copy-selection
|
||||
[ "$($TMUX show-buffer)" = "line" ] || exit 1
|
||||
|
||||
# Test that `next-word-end` wraps around indented line breaks.
|
||||
# Test that `next-word-end` stops at the end of the line.
|
||||
$TMUX send-keys -X next-word
|
||||
$TMUX send-keys -X next-word
|
||||
$TMUX send-keys -X begin-selection
|
||||
$TMUX send-keys -X next-word-end
|
||||
$TMUX send-keys -X next-word-end
|
||||
$TMUX send-keys -X copy-selection
|
||||
[ "$($TMUX show-buffer)" = "$(printf "words\n\tIndented")" ] || exit 1
|
||||
[ "$($TMUX show-buffer)" = "words" ] || exit 1
|
||||
|
||||
# Move to the next word for the following tests.
|
||||
$TMUX send-keys -X next-word
|
||||
|
||||
# Test that `next-word` wraps around un-indented line breaks.
|
||||
$TMUX send-keys -X next-word
|
||||
|
||||
@@ -4,7 +4,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -f/dev/null -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
TMP=$(mktemp)
|
||||
|
||||
@@ -4,7 +4,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
TMP=$(mktemp)
|
||||
|
||||
@@ -4,7 +4,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
TMP=$(mktemp)
|
||||
|
||||
@@ -4,7 +4,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
TMP=$(mktemp)
|
||||
|
||||
@@ -9,16 +9,12 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
sleep 1
|
||||
|
||||
TMP=$(mktemp)
|
||||
TMP2=$(mktemp)
|
||||
TMP3=$(mktemp)
|
||||
TMP4=$(mktemp)
|
||||
TMP5=$(mktemp)
|
||||
trap "rm -f $TMP $TMP2 $TMP3 $TMP4 $TMP5; $TMUX kill-server 2>/dev/null" 0 1 15
|
||||
trap "rm -f $TMP; $TMUX kill-server 2>/dev/null" 0 1 15
|
||||
|
||||
$TMUX -f/dev/null new -d -x80 -y24 || exit 1
|
||||
sleep 1
|
||||
@@ -35,13 +31,14 @@ query_decrpm() {
|
||||
_outfile=$1
|
||||
_mode=$2
|
||||
_setup=$3
|
||||
_n=$4
|
||||
|
||||
$TMUX respawnw -k -t:0 -- sh -c "
|
||||
exec 2>/dev/null
|
||||
stty raw -echo
|
||||
${_setup:+printf '$_setup'; sleep 0.2}
|
||||
printf '\033[%s\$p' "$_mode"
|
||||
dd bs=1 count=11 2>/dev/null | cat -v > $_outfile
|
||||
dd bs=1 count=$_n 2>/dev/null | cat -v > $_outfile
|
||||
sleep 0.2
|
||||
" || exit 1
|
||||
sleep 2
|
||||
@@ -50,7 +47,7 @@ query_decrpm() {
|
||||
# ------------------------------------------------------------------
|
||||
# Test 1: mode 2026 should be reset by default (Ps=2)
|
||||
# ------------------------------------------------------------------
|
||||
query_decrpm "$TMP" "?2026"
|
||||
query_decrpm "$TMP" "?2026" '' 11
|
||||
|
||||
actual=$(cat "$TMP")
|
||||
expected='^[[?2026;2$y'
|
||||
@@ -67,9 +64,9 @@ fi
|
||||
# ------------------------------------------------------------------
|
||||
# Test 2: set mode 2026 (SM ?2026), then query (expect Ps=1)
|
||||
# ------------------------------------------------------------------
|
||||
query_decrpm "$TMP2" "?2026" '\033[?2026h'
|
||||
query_decrpm "$TMP" "?2026" '\033[?2026h' 11
|
||||
|
||||
actual=$(cat "$TMP2")
|
||||
actual=$(cat "$TMP")
|
||||
expected='^[[?2026;1$y'
|
||||
|
||||
if [ "$actual" = "$expected" ]; then
|
||||
@@ -84,9 +81,9 @@ fi
|
||||
# ------------------------------------------------------------------
|
||||
# Test 3: mode 25 should return current value
|
||||
# ------------------------------------------------------------------
|
||||
query_decrpm "$TMP3" "?25" '\033[?25l'
|
||||
query_decrpm "$TMP" "?25" '\033[?25l' 9
|
||||
|
||||
actual=$(cat "$TMP3")
|
||||
actual=$(cat "$TMP")
|
||||
expected='^[[?25;2$y'
|
||||
|
||||
if [ "$actual" = "$expected" ]; then
|
||||
@@ -101,9 +98,9 @@ fi
|
||||
# ------------------------------------------------------------------
|
||||
# Test 4: mode ?9999 should return not recognized
|
||||
# ------------------------------------------------------------------
|
||||
query_decrpm "$TMP4" "?9999" '\033[?9999h'
|
||||
query_decrpm "$TMP" "?9999" '\033[?9999h' 11
|
||||
|
||||
actual=$(cat "$TMP4")
|
||||
actual=$(cat "$TMP")
|
||||
expected='^[[?9999;0$y'
|
||||
|
||||
if [ "$actual" = "$expected" ]; then
|
||||
@@ -122,9 +119,9 @@ exit $exit_status
|
||||
# ------------------------------------------------------------------
|
||||
# Test 5: mode 4 is reset by default
|
||||
# ------------------------------------------------------------------
|
||||
query_decrpm "$TMP5" "4" '\033[4h'
|
||||
query_decrpm "$TMP" "4" '\033[4h' 11
|
||||
|
||||
actual=$(cat "$TMP5")
|
||||
actual=$(cat "$TMP")
|
||||
expected='^[[4;1$y'
|
||||
|
||||
if [ "$actual" = "$expected" ]; then
|
||||
|
||||
@@ -6,7 +6,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
|
||||
# test_format $format $expected_result
|
||||
test_format()
|
||||
|
||||
@@ -7,7 +7,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
$TMUX -f/dev/null has -tfoo </dev/null 2>/dev/null && exit 1
|
||||
|
||||
@@ -7,7 +7,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
TMP=$(mktemp)
|
||||
|
||||
@@ -7,7 +7,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
TMP=$(mktemp)
|
||||
|
||||
@@ -7,7 +7,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
TMP=$(mktemp)
|
||||
|
||||
@@ -4,7 +4,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
sleep 1
|
||||
$TMUX -f/dev/null new -x20 -y2 -d \; set -g escape-time 0 || exit 1
|
||||
|
||||
@@ -6,7 +6,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
sleep 1
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
TMP=$(mktemp)
|
||||
|
||||
@@ -6,7 +6,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
TMP=$(mktemp)
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
PATH=/bin:/usr/bin
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
TERM=$($TMUX start \; show -gv default-terminal)
|
||||
TMP=$(mktemp)
|
||||
OUT=$(mktemp)
|
||||
SCRIPT=$(mktemp)
|
||||
#trap "rm -f $TMP $OUT $SCRIPT" 0 1 15
|
||||
trap "rm -f $TMP $OUT $SCRIPT" 0 1 15
|
||||
|
||||
cat <<EOF >$SCRIPT
|
||||
(
|
||||
|
||||
@@ -8,7 +8,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
TMP=$(mktemp)
|
||||
|
||||
@@ -6,7 +6,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
TMP=$(mktemp)
|
||||
|
||||
@@ -6,7 +6,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
TMP=$(mktemp)
|
||||
|
||||
@@ -4,7 +4,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
$TMUX new -d
|
||||
|
||||
@@ -7,7 +7,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
TMP=$(mktemp)
|
||||
|
||||
@@ -10,7 +10,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
TMP1=$(mktemp)
|
||||
|
||||
@@ -17,9 +17,9 @@ if command -v bash >/dev/null 2>&1; then
|
||||
fi
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
TMUX2="$TEST_TMUX -Ltest2"
|
||||
TMUX2="$TEST_TMUX -Ltest2 -f/dev/null"
|
||||
$TMUX2 kill-server 2>/dev/null
|
||||
|
||||
$TMUX2 -f/dev/null new -d "$TMUX -f/dev/null new -- $shell"
|
||||
|
||||
@@ -4,9 +4,9 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
TMUX2="$TEST_TMUX -Ltest2"
|
||||
TMUX2="$TEST_TMUX -Ltest2 -f/dev/null"
|
||||
$TMUX2 kill-server 2>/dev/null
|
||||
|
||||
TMP=$(mktemp)
|
||||
|
||||
@@ -90,7 +90,7 @@ You should see the Greek word 'kosme': "κόσμε"
|
||||
2.3.2 U-0000E000 = ee 80 80 = "" |
|
||||
2.3.3 U-0000FFFD = ef bf bd = "<22>" |
|
||||
2.3.4 U-0010FFFF = f4 8f bf bf = "" |
|
||||
2.3.5 U-00110000 = f4 90 80 80 = "<22><EFBFBD><EFBFBD><EFBFBD>" |
|
||||
2.3.5 U-00110000 = f4 90 80 80 = "<22>" |
|
||||
|
|
||||
3 Malformed sequences |
|
||||
|
|
||||
|
||||
@@ -4,7 +4,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
TMUX="$TEST_TMUX -Ltest -f/dev/null"
|
||||
TMP=$(mktemp)
|
||||
trap "rm -f $TMP" 0 1 15
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
@@ -627,21 +627,23 @@ screen_write_fast_copy(struct screen_write_ctx *ctx, struct screen *src,
|
||||
struct grid_line *gl, *sgl;
|
||||
struct grid_cell gc;
|
||||
u_int xx, yy, cx = s->cx, cy = s->cy;
|
||||
int yoff = 0;
|
||||
int xoff = 0, yoff = 0;
|
||||
struct visible_ranges *r;
|
||||
|
||||
if (nx == 0 || ny == 0)
|
||||
return;
|
||||
if (wp != NULL)
|
||||
if (wp != NULL) {
|
||||
xoff = wp->xoff;
|
||||
yoff = wp->yoff;
|
||||
}
|
||||
|
||||
for (yy = py; yy < py + ny; yy++) {
|
||||
if (yy >= gd->hsize + gd->sy)
|
||||
break;
|
||||
s->cx = cx;
|
||||
screen_write_initctx(ctx, &ttyctx, 0, 0);
|
||||
r = screen_redraw_get_visible_ranges(wp, px, s->cy + yoff, nx,
|
||||
NULL);
|
||||
r = screen_redraw_get_visible_ranges(wp, xoff + s->cx,
|
||||
s->cy + yoff, nx, NULL);
|
||||
for (xx = px; xx < px + nx; xx++) {
|
||||
gl = grid_get_line(gd, yy);
|
||||
sgl = grid_get_line(s->grid, s->cy);
|
||||
@@ -653,7 +655,7 @@ screen_write_fast_copy(struct screen_write_ctx *ctx, struct screen *src,
|
||||
break;
|
||||
grid_view_set_cell(s->grid, s->cx, s->cy, &gc);
|
||||
|
||||
if (!screen_redraw_is_visible(r, px))
|
||||
if (!screen_redraw_is_visible(r, xoff + s->cx))
|
||||
break;
|
||||
ttyctx.cell = &gc;
|
||||
ttyctx.flags &= (TTY_CTX_OVERLAY_SYNC|TTY_CTX_SYNC);
|
||||
@@ -2925,16 +2927,22 @@ void
|
||||
screen_write_alternateon(struct screen_write_ctx *ctx, struct grid_cell *gc,
|
||||
int cursor)
|
||||
{
|
||||
struct tty_ctx ttyctx;
|
||||
struct window_pane *wp = ctx->wp;
|
||||
struct tty_ctx ttyctx;
|
||||
struct window_pane *wp = ctx->wp;
|
||||
struct window_pane_resize *r, *r1;
|
||||
|
||||
if (wp != NULL && !options_get_number(wp->options, "alternate-screen"))
|
||||
return;
|
||||
|
||||
screen_write_collect_flush(ctx, 0, __func__);
|
||||
screen_alternate_on(ctx->s, gc, cursor);
|
||||
if (!screen_alternate_on(ctx->s, gc, cursor))
|
||||
return;
|
||||
|
||||
if (wp != NULL) {
|
||||
TAILQ_FOREACH_SAFE (r, &wp->resize_queue, entry, r1) {
|
||||
TAILQ_REMOVE(&wp->resize_queue, r, entry);
|
||||
free(r);
|
||||
}
|
||||
layout_fix_panes(wp->window, NULL);
|
||||
server_redraw_window_borders(wp->window);
|
||||
}
|
||||
@@ -2956,7 +2964,8 @@ screen_write_alternateoff(struct screen_write_ctx *ctx, struct grid_cell *gc,
|
||||
return;
|
||||
|
||||
screen_write_collect_flush(ctx, 0, __func__);
|
||||
screen_alternate_off(ctx->s, gc, cursor);
|
||||
if (!screen_alternate_off(ctx->s, gc, cursor))
|
||||
return;
|
||||
|
||||
if (wp != NULL) {
|
||||
layout_fix_panes(wp->window, NULL);
|
||||
|
||||
12
screen.c
12
screen.c
@@ -672,7 +672,7 @@ screen_reflow(struct screen *s, u_int new_x, u_int *cx, u_int *cy, int cursor)
|
||||
* Enter alternative screen mode. A copy of the visible screen is saved and the
|
||||
* history is not updated.
|
||||
*/
|
||||
void
|
||||
int
|
||||
screen_alternate_on(struct screen *s, struct grid_cell *gc, int cursor)
|
||||
{
|
||||
u_int sx, sy;
|
||||
@@ -681,7 +681,7 @@ screen_alternate_on(struct screen *s, struct grid_cell *gc, int cursor)
|
||||
#endif
|
||||
|
||||
if (SCREEN_IS_ALTERNATE(s))
|
||||
return;
|
||||
return 0;
|
||||
sx = screen_size_x(s);
|
||||
sy = screen_size_y(s);
|
||||
|
||||
@@ -703,10 +703,12 @@ screen_alternate_on(struct screen *s, struct grid_cell *gc, int cursor)
|
||||
|
||||
s->saved_flags = s->grid->flags;
|
||||
s->grid->flags &= ~GRID_HISTORY;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Exit alternate screen mode and restore the copied grid. */
|
||||
void
|
||||
int
|
||||
screen_alternate_off(struct screen *s, struct grid_cell *gc, int cursor)
|
||||
{
|
||||
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
||||
@@ -738,7 +740,7 @@ screen_alternate_off(struct screen *s, struct grid_cell *gc, int cursor)
|
||||
s->cx = screen_size_x(s) - 1;
|
||||
if (s->cy > screen_size_y(s) - 1)
|
||||
s->cy = screen_size_y(s) - 1;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Restore the saved grid. */
|
||||
@@ -767,6 +769,8 @@ screen_alternate_off(struct screen *s, struct grid_cell *gc, int cursor)
|
||||
s->cx = screen_size_x(s) - 1;
|
||||
if (s->cy > screen_size_y(s) - 1)
|
||||
s->cy = screen_size_y(s) - 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Get mode as a string. */
|
||||
|
||||
@@ -1623,10 +1623,7 @@ server_client_resize_timer(__unused int fd, __unused short events, void *data)
|
||||
static void
|
||||
server_client_check_pane_resize(struct window_pane *wp)
|
||||
{
|
||||
struct window_pane_resize *r;
|
||||
struct window_pane_resize *r1;
|
||||
struct window_pane_resize *first;
|
||||
struct window_pane_resize *last;
|
||||
struct window_pane_resize *r, *r1, *first, *last;
|
||||
struct timeval tv = { .tv_usec = 250000 };
|
||||
|
||||
if (TAILQ_EMPTY(&wp->resize_queue))
|
||||
@@ -1852,12 +1849,13 @@ server_client_reset_state(struct client *c)
|
||||
cx = wp->xoff + (int)s->cx - (int)ox;
|
||||
cy = wp->yoff + (int)s->cy - (int)oy;
|
||||
|
||||
r = screen_redraw_get_visible_ranges(wp, cx, cy, 1, NULL);
|
||||
if (!screen_redraw_is_visible(r, cx))
|
||||
cursor = 0;
|
||||
|
||||
if (status_at_line(c) == 0)
|
||||
cy += status_line_size(c);
|
||||
}
|
||||
r = screen_redraw_get_visible_ranges(wp, cx, cy, 1, NULL);
|
||||
if (!screen_redraw_is_visible(r, cx))
|
||||
cursor = 0;
|
||||
|
||||
if (!cursor)
|
||||
mode &= ~MODE_CURSOR;
|
||||
|
||||
130
tmux.1
130
tmux.1
@@ -1206,7 +1206,7 @@ Kill the
|
||||
.Nm
|
||||
server and clients and destroy all sessions.
|
||||
.It Xo Ic kill\-session
|
||||
.Op Fl aC
|
||||
.Op Fl aCg
|
||||
.Op Fl t Ar target\-session
|
||||
.Xc
|
||||
Destroy the given session, closing any windows linked to it and no other
|
||||
@@ -1214,6 +1214,10 @@ sessions, and detaching all clients attached to it.
|
||||
If
|
||||
.Fl a
|
||||
is given, all sessions but the specified one is killed.
|
||||
If
|
||||
.Fl g
|
||||
is given and the session is in a session group, all sessions in the group are
|
||||
killed.
|
||||
The
|
||||
.Fl C
|
||||
flag clears alerts (bell, activity, or silence) in all windows linked to the
|
||||
@@ -2310,7 +2314,6 @@ cursor on that line.
|
||||
Scroll pane in copy\-mode when bound to a mouse drag event.
|
||||
.Fl e
|
||||
causes copy mode to exit when at the bottom.
|
||||
.Pp
|
||||
.It Xo
|
||||
.Ic scroll\-top
|
||||
.Xc
|
||||
@@ -2666,7 +2669,7 @@ but a different format may be specified with
|
||||
.Fl F .
|
||||
.Tg capturep
|
||||
.It Xo Ic capture\-pane
|
||||
.Op Fl aepPqCJMN
|
||||
.Op Fl aeFHLpPqCJMN
|
||||
.Op Fl b Ar buffer\-name
|
||||
.Op Fl E Ar end\-line
|
||||
.Op Fl S Ar start\-line
|
||||
@@ -2706,6 +2709,26 @@ implies
|
||||
.Fl P
|
||||
captures only any output that the pane has received that is the beginning of an
|
||||
as-yet incomplete escape sequence.
|
||||
.Fl L
|
||||
includes the line number at the start of each line and
|
||||
.Fl F
|
||||
includes the flags (where
|
||||
.Ql -
|
||||
is no flags,
|
||||
.Ql D
|
||||
is an unused line,
|
||||
.Ql O
|
||||
is a line marked as output,
|
||||
.Ql P
|
||||
is a line marked as a prompt,
|
||||
.Ql X
|
||||
is a line containing extended cells and
|
||||
.Ql H
|
||||
is a line with hyperlinks).
|
||||
With
|
||||
.Fl H ,
|
||||
only hyperlinks in the specified lines are captured.
|
||||
Multiple hyperlinks on the same line are separated by spaces.
|
||||
.Pp
|
||||
.Fl S
|
||||
and
|
||||
@@ -2721,7 +2744,7 @@ the end of the visible pane.
|
||||
The default is to capture only the visible contents of the pane.
|
||||
.It Xo
|
||||
.Ic choose\-client
|
||||
.Op Fl NryZ
|
||||
.Op Fl hkNryZ
|
||||
.Op Fl F Ar format
|
||||
.Op Fl f Ar filter
|
||||
.Op Fl K Ar key\-format
|
||||
@@ -2792,12 +2815,20 @@ If a filter would lead to an empty list, it is ignored.
|
||||
specifies the format for each item in the list and
|
||||
.Fl K
|
||||
a format for each shortcut key; both are evaluated once for each line.
|
||||
.Pp
|
||||
.Fl N
|
||||
starts without the preview or if given twice with the larger preview.
|
||||
This command works only if at least one client is attached.
|
||||
.Fl h
|
||||
hides the pane containing the mode.
|
||||
.Fl k
|
||||
kills the pane when the mode is exited.
|
||||
.Pp
|
||||
The
|
||||
.Ic choose-client
|
||||
command works only if at least one client is attached.
|
||||
.It Xo
|
||||
.Ic choose\-tree
|
||||
.Op Fl GNrswyZ
|
||||
.Op Fl GhkNrswyZ
|
||||
.Op Fl F Ar format
|
||||
.Op Fl f Ar filter
|
||||
.Op Fl K Ar key\-format
|
||||
@@ -2882,15 +2913,30 @@ If a filter would lead to an empty list, it is ignored.
|
||||
specifies the format for each item in the tree and
|
||||
.Fl K
|
||||
a format for each shortcut key; both are evaluated once for each line.
|
||||
.Fl N
|
||||
starts without the preview or if given twice with the larger preview.
|
||||
.Fl G
|
||||
includes all sessions in any session groups in the tree rather than only the
|
||||
first.
|
||||
This command works only if at least one client is attached.
|
||||
.Pp
|
||||
.Fl N
|
||||
starts without the preview or if given twice with the larger preview.
|
||||
.Fl h
|
||||
hides the pane containing the mode.
|
||||
.Fl k
|
||||
kills the pane when the mode is exited.
|
||||
.Fl h
|
||||
and
|
||||
.Fl k
|
||||
are intended to ease use of the mode in a floating pane; for example:
|
||||
.Bd -literal -offset indent
|
||||
bind s 'new-pane -x50% -y50% -E; choose-tree -hks'
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
.Ic choose-tree
|
||||
command works only if at least one client is attached.
|
||||
.It Xo
|
||||
.Ic customize\-mode
|
||||
.Op Fl NZ
|
||||
.Op Fl kNZ
|
||||
.Op Fl F Ar format
|
||||
.Op Fl f Ar filter
|
||||
.Op Fl t Ar target\-pane
|
||||
@@ -2936,9 +2982,15 @@ the item in the list is not shown, otherwise it is shown.
|
||||
If a filter would lead to an empty list, it is ignored.
|
||||
.Fl F
|
||||
specifies the format for each item in the tree.
|
||||
.Pp
|
||||
.Fl N
|
||||
starts without the option information.
|
||||
This command works only if at least one client is attached.
|
||||
.Fl k
|
||||
kills the pane when the mode is exited.
|
||||
.Pp
|
||||
The
|
||||
.Ic customize-mode
|
||||
command works only if at least one client is attached.
|
||||
.It Xo
|
||||
.Tg displayp
|
||||
.Ic display\-panes
|
||||
@@ -3009,7 +3061,9 @@ The default is
|
||||
.Fl Z
|
||||
zooms the pane.
|
||||
.Pp
|
||||
This command works only if at least one client is attached.
|
||||
The
|
||||
.Ic find-window
|
||||
command works only if at least one client is attached.
|
||||
.Tg floatp
|
||||
.It Xo Ic float\-pane
|
||||
.Op Fl h Ar height
|
||||
@@ -3371,6 +3425,7 @@ but a different format may be specified with
|
||||
.Op Fl s Ar style
|
||||
.Op Fl S Ar active\-border\-style
|
||||
.Op Fl t Ar target\-pane
|
||||
.Op Fl T Ar title
|
||||
.Op Ar shell\-command Op Ar argument ...
|
||||
.Xc
|
||||
.D1 Pq alias: Ic newp
|
||||
@@ -3389,6 +3444,8 @@ sets the border style when the pane is active and
|
||||
.Fl R
|
||||
sets the border style when the pane is inactive (see
|
||||
.Sx STYLES ) .
|
||||
.Fl T
|
||||
sets the pane title.
|
||||
.Pp
|
||||
.Fl h
|
||||
does a horizontal split and
|
||||
@@ -3433,15 +3490,16 @@ but also sets the
|
||||
option for this pane to
|
||||
.Ar message .
|
||||
.Pp
|
||||
An empty
|
||||
.Ar shell\-command
|
||||
(\[aq]\[aq]) will create a pane with no command running in it.
|
||||
.Fl E ,
|
||||
or an empty
|
||||
.Ar shell\-command ,
|
||||
(\[aq]\[aq]) will create an empty pane with no command running in it;
|
||||
.Ic display-message
|
||||
.Fl I
|
||||
can write to an empty pane.
|
||||
The
|
||||
.Fl I
|
||||
flag (if
|
||||
.Ar shell\-command
|
||||
is not specified or empty)
|
||||
will create an empty pane and forward any output from stdin to it.
|
||||
flag will create an empty pane and forward any output from stdin to it.
|
||||
For example:
|
||||
.Bd -literal -offset indent
|
||||
$ make 2>&1|tmux splitw \-dI &
|
||||
@@ -3785,6 +3843,7 @@ the command behaves like
|
||||
.Op Fl s Ar style
|
||||
.Op Fl S Ar active\-border\-style
|
||||
.Op Fl t Ar target\-pane
|
||||
.Op Fl T Ar title
|
||||
.Op Ar shell\-command Op Ar argument ...
|
||||
.Xc
|
||||
.D1 Pq alias: Ic splitw
|
||||
@@ -4848,6 +4907,12 @@ command to show the indicator for the active pane.
|
||||
Set the colour used by the
|
||||
.Ic display\-panes
|
||||
command to show the indicators for inactive panes.
|
||||
.It Ic display\-panes\-format Ar format
|
||||
Set the
|
||||
.Ar format
|
||||
of the text shown by the
|
||||
.Ic display\-panes
|
||||
command, expanded for each pane.
|
||||
.It Ic display\-panes\-time Ar time
|
||||
Set the time in milliseconds for which the indicators shown by the
|
||||
.Ic display\-panes
|
||||
@@ -6375,9 +6440,15 @@ gives
|
||||
gives
|
||||
.Ql Sun Oct 25 09:25:02 2015 .
|
||||
Adding
|
||||
.Ql p (
|
||||
.Ql `t/p` )
|
||||
.Ql p
|
||||
.Pq Ql t/p
|
||||
will use shorter but less accurate time format for times in the past.
|
||||
.Ql r
|
||||
.Pq Ql t/r
|
||||
will show the time relative to the current time, for example
|
||||
.Ql \-1m
|
||||
or
|
||||
.Ql +2m23s .
|
||||
A custom format may be given using an
|
||||
.Ql f
|
||||
suffix (note that
|
||||
@@ -6405,12 +6476,17 @@ of the variable respectively.
|
||||
.Ql q:\&
|
||||
will escape
|
||||
.Xr sh 1
|
||||
special characters or with a
|
||||
special characters; with a
|
||||
.Ql h
|
||||
suffix, escape hash characters (so
|
||||
.Ql #
|
||||
becomes
|
||||
.Ql ## ) .
|
||||
.Ql ## ) ;
|
||||
or with
|
||||
.Ql a
|
||||
escape
|
||||
.Nm
|
||||
command arguments.
|
||||
.Ql E:\&
|
||||
will expand the format twice, for example
|
||||
.Ql #{E:status\-left}
|
||||
@@ -7703,7 +7779,7 @@ The buffer commands are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Xo
|
||||
.Ic choose\-buffer
|
||||
.Op Fl NryZ
|
||||
.Op Fl kNryZ
|
||||
.Op Fl F Ar format
|
||||
.Op Fl f Ar filter
|
||||
.Op Fl K Ar key\-format
|
||||
@@ -7774,7 +7850,11 @@ specifies the format for each item in the list and
|
||||
a format for each shortcut key; both are evaluated once for each line.
|
||||
.Fl N
|
||||
starts without the preview.
|
||||
This command works only if at least one client is attached.
|
||||
.Fl k
|
||||
kills the pane when the mode is exited.
|
||||
The
|
||||
.Ic choose-buffer
|
||||
command works only if at least one client is attached.
|
||||
.Tg clearhist
|
||||
.It Xo Ic clear\-history
|
||||
.Op Fl H
|
||||
|
||||
17
tmux.h
17
tmux.h
@@ -780,6 +780,7 @@ struct colour_palette {
|
||||
#define GRID_LINE_DEAD 0x4
|
||||
#define GRID_LINE_START_PROMPT 0x8
|
||||
#define GRID_LINE_START_OUTPUT 0x10
|
||||
#define GRID_LINE_HYPERLINK 0x20
|
||||
|
||||
/* Grid string flags. */
|
||||
#define GRID_STRING_WITH_SEQUENCES 0x1
|
||||
@@ -1180,6 +1181,8 @@ struct window_mode_entry {
|
||||
struct screen *screen;
|
||||
u_int prefix;
|
||||
|
||||
int kill;
|
||||
|
||||
TAILQ_ENTRY(window_mode_entry) entry;
|
||||
};
|
||||
|
||||
@@ -1270,7 +1273,7 @@ struct window_pane {
|
||||
#define PANE_FOCUSED 0x4
|
||||
#define PANE_VISITED 0x8
|
||||
#define PANE_ZOOMED 0x10
|
||||
/* unused 0x20 */
|
||||
/* 0x20 unused */
|
||||
#define PANE_INPUTOFF 0x40
|
||||
#define PANE_CHANGED 0x80
|
||||
#define PANE_EXITED 0x100
|
||||
@@ -1482,8 +1485,7 @@ TAILQ_HEAD(layout_cells, layout_cell);
|
||||
struct layout_cell {
|
||||
enum layout_type type;
|
||||
|
||||
/* unused 0x1 */
|
||||
#define LAYOUT_CELL_FLOATING 0x2
|
||||
#define LAYOUT_CELL_FLOATING 0x1
|
||||
int flags;
|
||||
|
||||
struct layout_cell *parent;
|
||||
@@ -3397,8 +3399,8 @@ void screen_hide_selection(struct screen *);
|
||||
int screen_check_selection(struct screen *, u_int, u_int);
|
||||
int screen_select_cell(struct screen *, struct grid_cell *,
|
||||
const struct grid_cell *);
|
||||
void screen_alternate_on(struct screen *, struct grid_cell *, int);
|
||||
void screen_alternate_off(struct screen *, struct grid_cell *, int);
|
||||
int screen_alternate_on(struct screen *, struct grid_cell *, int);
|
||||
int screen_alternate_off(struct screen *, struct grid_cell *, int);
|
||||
const char *screen_mode_to_string(int);
|
||||
const char *screen_print(struct screen *, int);
|
||||
|
||||
@@ -3547,12 +3549,13 @@ void layout_assign_pane(struct layout_cell *, struct window_pane *,
|
||||
int);
|
||||
struct layout_cell *layout_split_pane(struct window_pane *, enum layout_type,
|
||||
int, int);
|
||||
struct layout_cell *layout_floating_pane(struct window *, u_int, u_int, int,
|
||||
int);
|
||||
void layout_close_pane(struct window_pane *);
|
||||
int layout_spread_cell(struct window *, struct layout_cell *);
|
||||
void layout_spread_out(struct window_pane *);
|
||||
struct layout_cell *layout_get_floating_cell(struct cmdq_item *, struct args *,
|
||||
struct window *, struct window_pane *, struct layout_cell *,
|
||||
char **);
|
||||
struct window *, struct window_pane *, char **);
|
||||
struct layout_cell *layout_get_tiled_cell(struct cmdq_item *, struct args *,
|
||||
struct window *, struct window_pane *, int, char **);
|
||||
|
||||
|
||||
@@ -82,6 +82,7 @@ struct window_client_modedata {
|
||||
char *format;
|
||||
char *key_format;
|
||||
char *command;
|
||||
int hide_preview_this_pane;
|
||||
|
||||
struct window_client_itemdata **item_list;
|
||||
u_int item_size;
|
||||
@@ -162,9 +163,10 @@ window_client_build(void *modedata, struct sort_criteria *sort_crit,
|
||||
}
|
||||
|
||||
static void
|
||||
window_client_draw(__unused void *modedata, void *itemdata,
|
||||
window_client_draw(void *modedata, void *itemdata,
|
||||
struct screen_write_ctx *ctx, u_int sx, u_int sy)
|
||||
{
|
||||
struct window_client_modedata *data = modedata;
|
||||
struct window_client_itemdata *item = itemdata;
|
||||
struct client *c = item->c;
|
||||
struct screen *s = ctx->s;
|
||||
@@ -174,6 +176,12 @@ window_client_draw(__unused void *modedata, void *itemdata,
|
||||
if (c->session == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS))
|
||||
return;
|
||||
wp = c->session->curw->window->active;
|
||||
if (data->hide_preview_this_pane && wp == data->wp) {
|
||||
if (!TAILQ_EMPTY(&c->session->curw->window->last_panes))
|
||||
wp = TAILQ_FIRST(&c->session->curw->window->last_panes);
|
||||
else
|
||||
wp = NULL;
|
||||
}
|
||||
|
||||
lines = status_line_size(c);
|
||||
if (lines >= sy)
|
||||
@@ -184,7 +192,8 @@ window_client_draw(__unused void *modedata, void *itemdata,
|
||||
at = 0;
|
||||
|
||||
screen_write_cursormove(ctx, cx, cy + at, 0);
|
||||
screen_write_preview(ctx, &wp->base, sx, sy - 2 - lines);
|
||||
if (wp != NULL)
|
||||
screen_write_preview(ctx, &wp->base, sx, sy - 2 - lines);
|
||||
|
||||
if (at != 0)
|
||||
screen_write_cursormove(ctx, cx, cy + 2, 0);
|
||||
@@ -270,6 +279,7 @@ window_client_init(struct window_mode_entry *wme,
|
||||
|
||||
wme->data = data = xcalloc(1, sizeof *data);
|
||||
data->wp = wp;
|
||||
data->hide_preview_this_pane = args != NULL && args_has(args, 'h');
|
||||
|
||||
if (args == NULL || !args_has(args, 'F'))
|
||||
data->format = xstrdup(WINDOW_CLIENT_DEFAULT_FORMAT);
|
||||
|
||||
@@ -113,6 +113,7 @@ struct window_tree_modedata {
|
||||
char *key_format;
|
||||
char *command;
|
||||
int squash_groups;
|
||||
int hide_preview_this_pane;
|
||||
int prompt_flags;
|
||||
|
||||
struct window_tree_itemdata **item_list;
|
||||
@@ -289,6 +290,8 @@ window_tree_build_window(struct session *s, struct winlink *wl,
|
||||
if (n == 0)
|
||||
goto empty;
|
||||
for (i = 0; i < n; i++) {
|
||||
if (data->hide_preview_this_pane && l[i] == data->wp)
|
||||
continue;
|
||||
if (window_tree_filter_pane(s, wl, l[i], filter))
|
||||
window_tree_build_pane(s, wl, l[i], modedata, mti);
|
||||
}
|
||||
@@ -580,6 +583,10 @@ window_tree_draw_window(struct window_tree_modedata *data, struct session *s,
|
||||
struct options *oo;
|
||||
|
||||
total = window_count_panes(w, 1);
|
||||
if (data->hide_preview_this_pane && data->wp->window == w)
|
||||
total--;
|
||||
if (total == 0)
|
||||
return;
|
||||
|
||||
if (sx / total < 24) {
|
||||
visible = sx / 24;
|
||||
@@ -590,6 +597,8 @@ window_tree_draw_window(struct window_tree_modedata *data, struct session *s,
|
||||
|
||||
current = 0;
|
||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||
if (data->hide_preview_this_pane && wp == data->wp)
|
||||
continue;
|
||||
if (wp == w->active)
|
||||
break;
|
||||
current++;
|
||||
@@ -653,6 +662,8 @@ window_tree_draw_window(struct window_tree_modedata *data, struct session *s,
|
||||
|
||||
i = loop = 0;
|
||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||
if (data->hide_preview_this_pane && wp == data->wp)
|
||||
continue;
|
||||
if (loop == end)
|
||||
break;
|
||||
if (loop < start) {
|
||||
@@ -704,6 +715,7 @@ static void
|
||||
window_tree_draw(void *modedata, void *itemdata, struct screen_write_ctx *ctx,
|
||||
u_int sx, u_int sy)
|
||||
{
|
||||
struct window_tree_modedata *data = modedata;
|
||||
struct window_tree_itemdata *item = itemdata;
|
||||
struct session *sp;
|
||||
struct winlink *wl;
|
||||
@@ -723,7 +735,8 @@ window_tree_draw(void *modedata, void *itemdata, struct screen_write_ctx *ctx,
|
||||
window_tree_draw_window(modedata, sp, wl, ctx, sx, sy);
|
||||
break;
|
||||
case WINDOW_TREE_PANE:
|
||||
screen_write_preview(ctx, &wp->base, sx, sy);
|
||||
if (!data->hide_preview_this_pane || wp != data->wp)
|
||||
screen_write_preview(ctx, &wp->base, sx, sy);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -932,6 +945,7 @@ window_tree_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
||||
else
|
||||
data->command = xstrdup(args_string(args, 0));
|
||||
data->squash_groups = !args_has(args, 'G');
|
||||
data->hide_preview_this_pane = args_has(args, 'h');
|
||||
if (args_has(args, 'y'))
|
||||
data->prompt_flags = PROMPT_ACCEPT;
|
||||
|
||||
|
||||
6
window.c
6
window.c
@@ -1280,6 +1280,7 @@ window_pane_set_mode(struct window_pane *wp, struct window_pane *swp,
|
||||
TAILQ_INSERT_HEAD(&wp->modes, wme, entry);
|
||||
wme->screen = wme->mode->init(wme, fs, args);
|
||||
}
|
||||
wme->kill = args_has(args, 'k');
|
||||
wp->screen = wme->screen;
|
||||
|
||||
wp->flags |= (PANE_REDRAW|PANE_REDRAWSCROLLBAR|PANE_CHANGED);
|
||||
@@ -1297,11 +1298,13 @@ window_pane_reset_mode(struct window_pane *wp)
|
||||
{
|
||||
struct window_mode_entry *wme, *next;
|
||||
struct window *w = wp->window;
|
||||
int kill;
|
||||
|
||||
if (TAILQ_EMPTY(&wp->modes))
|
||||
return;
|
||||
|
||||
wme = TAILQ_FIRST(&wp->modes);
|
||||
kill = wme->kill;
|
||||
TAILQ_REMOVE(&wp->modes, wme, entry);
|
||||
wme->mode->free(wme);
|
||||
free(wme);
|
||||
@@ -1324,6 +1327,9 @@ window_pane_reset_mode(struct window_pane *wp)
|
||||
server_redraw_window_borders(wp->window);
|
||||
server_status_window(wp->window);
|
||||
notify_pane("pane-mode-changed", wp);
|
||||
|
||||
if (kill)
|
||||
server_kill_pane(wp);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Reference in New Issue
Block a user