mirror of
https://github.com/tmux/tmux.git
synced 2026-03-12 03:25:45 +00:00
Compare commits
124 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
caa90735cf | ||
|
|
0f26739c9f | ||
|
|
ae2c5ad768 | ||
|
|
2bff5e7867 | ||
|
|
90f2a417af | ||
|
|
7c07f5f640 | ||
|
|
69df38f8d8 | ||
|
|
5e30b81825 | ||
|
|
3a47dec424 | ||
|
|
7b17618890 | ||
|
|
71bc255e6f | ||
|
|
8f990c573c | ||
|
|
3f1d6102f3 | ||
|
|
3712b41aba | ||
|
|
4bcb64f8c1 | ||
|
|
a651b08a2f | ||
|
|
3b35daacf7 | ||
|
|
18f36906a9 | ||
|
|
5fee4638e0 | ||
|
|
d52f579fd5 | ||
|
|
2fef10b9ac | ||
|
|
f3221941f2 | ||
|
|
d98d316903 | ||
|
|
97ecb4f9d8 | ||
|
|
ca6a121e63 | ||
|
|
e354b0e40f | ||
|
|
0ccfb61bb0 | ||
|
|
4b39120d22 | ||
|
|
76950a6401 | ||
|
|
909d962d3a | ||
|
|
dde53cfde1 | ||
|
|
0adb60b3a6 | ||
|
|
a2dd7daf4e | ||
|
|
3a8e56b282 | ||
|
|
36202a63e9 | ||
|
|
abad809e7a | ||
|
|
0f2f783584 | ||
|
|
bcd6b41674 | ||
|
|
92053cb492 | ||
|
|
14cb489a3b | ||
|
|
54e2205e54 | ||
|
|
99b0f48b2e | ||
|
|
c12711affd | ||
|
|
e4b4125310 | ||
|
|
6b2d850e54 | ||
|
|
0daeefefdb | ||
|
|
d520dae6ac | ||
|
|
03d01eabb5 | ||
|
|
65d6278f88 | ||
|
|
c48d09ec88 | ||
|
|
4a51a9d9d5 | ||
|
|
b938212563 | ||
|
|
accaff8ac0 | ||
|
|
45965fb020 | ||
|
|
6ac39d5cdb | ||
|
|
9794c03537 | ||
|
|
1b221a56ea | ||
|
|
eb6fd6ff80 | ||
|
|
9d041d8e6c | ||
|
|
5172014668 | ||
|
|
b853054e71 | ||
|
|
a6a294c8f8 | ||
|
|
1e0eb914d9 | ||
|
|
ae1a6c2fc5 | ||
|
|
e802b683ea | ||
|
|
55cd4c7bc7 | ||
|
|
a4eaac359a | ||
|
|
ee45a8a149 | ||
|
|
b08e451c91 | ||
|
|
2c0f826c36 | ||
|
|
bcab77e266 | ||
|
|
d8398af770 | ||
|
|
30348edc7c | ||
|
|
59ff9b8128 | ||
|
|
2c9bdd9e32 | ||
|
|
21240c1a8f | ||
|
|
c8ecbf38ab | ||
|
|
194a121ef6 | ||
|
|
8867951144 | ||
|
|
fd13731049 | ||
|
|
c68ceca8cd | ||
|
|
efaf4c16cf | ||
|
|
2ad09ab5af | ||
|
|
1f209ed030 | ||
|
|
3c876235cc | ||
|
|
afa4e3ed9c | ||
|
|
c376c5a817 | ||
|
|
92a77e7654 | ||
|
|
4612419c14 | ||
|
|
c799425069 | ||
|
|
428be9803c | ||
|
|
bba588752f | ||
|
|
311dad8c28 | ||
|
|
93062ad099 | ||
|
|
22e594fcea | ||
|
|
02580ac134 | ||
|
|
b723f50e65 | ||
|
|
4a2e75fc8c | ||
|
|
9420758127 | ||
|
|
87997efe8d | ||
|
|
69e0f28333 | ||
|
|
51a0dbb172 | ||
|
|
7934e7a6b5 | ||
|
|
aebbb15fe2 | ||
|
|
48371216df | ||
|
|
e30f9dc1fa | ||
|
|
21993105e5 | ||
|
|
0f25ad3ca3 | ||
|
|
f9c7c50a93 | ||
|
|
0b44ad99b5 | ||
|
|
78d707dc83 | ||
|
|
3385159c94 | ||
|
|
f184c6f06c | ||
|
|
5a551ac57f | ||
|
|
53fde21bb8 | ||
|
|
689f4bfac2 | ||
|
|
85af9c9c9d | ||
|
|
95c38087db | ||
|
|
fa6deb5866 | ||
|
|
a71c262d5f | ||
|
|
f731ae4a2d | ||
|
|
8c8ce08d79 | ||
|
|
de4f817bd6 | ||
|
|
623e35f594 |
89
CHANGES
89
CHANGES
@@ -1,3 +1,88 @@
|
|||||||
|
CHANGES FROM 2.4 to 2.5 09 May 2017
|
||||||
|
|
||||||
|
* Reset updated flag when restarting #() command so that new output is properly
|
||||||
|
recognised. GitHub issue 922.
|
||||||
|
|
||||||
|
* Fix ECH with a background colour.
|
||||||
|
|
||||||
|
* Do not rely on the terminal not moving the cursor after DL or EL.
|
||||||
|
|
||||||
|
* Fix send-keys and send-prefix in copy-mode (so C-b C-b works). GitHub issue
|
||||||
|
905.
|
||||||
|
|
||||||
|
* Set the current pane for rotate-window so it works in command sequences.
|
||||||
|
|
||||||
|
* Add pane_mode format.
|
||||||
|
|
||||||
|
* Differentiate M-Up from Escape+Up when possible (that is, in terminals with
|
||||||
|
xterm(1) style function keys). GitHub issue 907.
|
||||||
|
|
||||||
|
* Add session_stack and window_stack_index formats.
|
||||||
|
|
||||||
|
* Some new control mode notifications and corresponding hooks:
|
||||||
|
pane-mode-changed, window-pane-changed, client-session-changed,
|
||||||
|
session-window-changed.
|
||||||
|
|
||||||
|
* Format pane_search_string for last search term while in copy mode (useful
|
||||||
|
with command-prompt -I).
|
||||||
|
|
||||||
|
* Fix a problem with high CPU usage and multiple clients with #(). GitHub issue
|
||||||
|
889.
|
||||||
|
|
||||||
|
* Fix UTF-8 combining characters in column 0.
|
||||||
|
|
||||||
|
* Fix reference counting so that panes are properly destroyed and their
|
||||||
|
processes killed.
|
||||||
|
|
||||||
|
* Clamp SU (CSI S) parameter to work around a bug in Konsole.
|
||||||
|
|
||||||
|
* Tweak line wrapping in full width panes to play more nicely with terminal
|
||||||
|
copy and paste.
|
||||||
|
|
||||||
|
* Fix when we emit SGR 0 in capture-pane -e.
|
||||||
|
|
||||||
|
* Do not change TERM until after config file parsing has finished, so that
|
||||||
|
commands run inside the config file can use it to make decisions (typically
|
||||||
|
about default-terminal).
|
||||||
|
|
||||||
|
* Make the initial client wait until config file parsing has finished to avoid
|
||||||
|
racing with commands.
|
||||||
|
|
||||||
|
* Fix core when if-shell fails.
|
||||||
|
|
||||||
|
* Only use ED to clear screen if the pane is at the bottom.
|
||||||
|
|
||||||
|
* Fix multibyte UTF-8 output.
|
||||||
|
|
||||||
|
* Code improvements around target (-t) resolution.
|
||||||
|
|
||||||
|
* Change how the default target (for commands without -t) is managed across
|
||||||
|
command sequences: now it is set up at the start and commands are required
|
||||||
|
to update it if needed. Fixes binding command sequences to mouse keys.
|
||||||
|
|
||||||
|
* Make if-shell from the config file work correctly.
|
||||||
|
|
||||||
|
* Change to always check the root key table if no binding is found in the
|
||||||
|
current table (prefix table or copy-mode table or whatever). This means that
|
||||||
|
root key bindings will take effect even in copy mode, if not overridden by a
|
||||||
|
copy mode key binding.
|
||||||
|
|
||||||
|
* Fix so that the history file works again.
|
||||||
|
|
||||||
|
* Run config file without a client rather than using the first client, restores
|
||||||
|
previous behaviour.
|
||||||
|
|
||||||
|
* If a #() command doesn't exit, continue to read from it and use its last full
|
||||||
|
line of output.
|
||||||
|
|
||||||
|
* Handle slow terminals and fast output better: when the amount of data
|
||||||
|
outstanding gets too large, discard output until it is drained and we are
|
||||||
|
able to do a full redraw. Prevents tmux sitting on a huge buffer that the
|
||||||
|
terminal will take forever to consume.
|
||||||
|
|
||||||
|
* Do not redraw a client unless we realistically think it can accept the data -
|
||||||
|
defer redraws until the client has nothing else waiting to write.
|
||||||
|
|
||||||
CHANGES FROM 2.3 to 2.4 20 April 2017
|
CHANGES FROM 2.3 to 2.4 20 April 2017
|
||||||
|
|
||||||
Incompatible Changes
|
Incompatible Changes
|
||||||
@@ -23,12 +108,12 @@ Incompatible Changes
|
|||||||
bind -Tcopy-mode C-Up send -X scroll-up
|
bind -Tcopy-mode C-Up send -X scroll-up
|
||||||
bind -Tcopy-mode WheelUpPane send -N5 -X scroll-up
|
bind -Tcopy-mode WheelUpPane send -N5 -X scroll-up
|
||||||
|
|
||||||
This changes allows the full command parser (including command sequences) and
|
These changes allows the full command parser (including command sequences) and
|
||||||
command set to be used - for example, the normal command prompt with editing
|
command set to be used - for example, the normal command prompt with editing
|
||||||
and history is now used for searching, jumping, and so on instead of a custom
|
and history is now used for searching, jumping, and so on instead of a custom
|
||||||
one. The default C-r binding is now:
|
one. The default C-r binding is now:
|
||||||
|
|
||||||
bind -Tcopy-mode C-r command-prompt -p'search up' "send -X search-backward '%%'"
|
bind -Tcopy-mode C-r command-prompt -p'search up' "send -X search-backward-incremental '%%'"
|
||||||
|
|
||||||
There are also some new commmands available with send -X, such as
|
There are also some new commmands available with send -X, such as
|
||||||
copy-pipe-and-cancel.
|
copy-pipe-and-cancel.
|
||||||
|
|||||||
@@ -8,8 +8,6 @@ CLEANFILES = tmux.1.mdoc tmux.1.man
|
|||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
CHANGES FAQ README TODO COPYING example_tmux.conf compat/*.[ch] \
|
CHANGES FAQ README TODO COPYING example_tmux.conf compat/*.[ch] \
|
||||||
osdep-*.c mdoc2man.awk tmux.1
|
osdep-*.c mdoc2man.awk tmux.1
|
||||||
dist-hook:
|
|
||||||
grep "^#enable_debug=" configure
|
|
||||||
|
|
||||||
# Preprocessor flags.
|
# Preprocessor flags.
|
||||||
AM_CPPFLAGS += @XOPEN_DEFINES@ -DTMUX_CONF="\"$(sysconfdir)/tmux.conf\""
|
AM_CPPFLAGS += @XOPEN_DEFINES@ -DTMUX_CONF="\"$(sysconfdir)/tmux.conf\""
|
||||||
@@ -153,7 +151,6 @@ dist_tmux_SOURCES = \
|
|||||||
options.c \
|
options.c \
|
||||||
paste.c \
|
paste.c \
|
||||||
proc.c \
|
proc.c \
|
||||||
pty.c \
|
|
||||||
resize.c \
|
resize.c \
|
||||||
screen-redraw.c \
|
screen-redraw.c \
|
||||||
screen-write.c \
|
screen-write.c \
|
||||||
|
|||||||
24
SYNCING
24
SYNCING
@@ -140,16 +140,12 @@ to compat/ as and when appropriate.
|
|||||||
Release tmux for next version
|
Release tmux for next version
|
||||||
=============================
|
=============================
|
||||||
|
|
||||||
1. Comment the "enable_debug=yes" line in configure.ac, since releases
|
1. Update and commit README and CHANGES. The former should be checked for
|
||||||
don't have debugging enabled, otherwise make(1) aborts when
|
|
||||||
preparing the distribution.
|
|
||||||
|
|
||||||
2. Update and commit README and CHANGES. The former should be checked for
|
|
||||||
anything outdated and updated with a list of things that might break
|
anything outdated and updated with a list of things that might break
|
||||||
upgrades and the latter should mention all the major changes since
|
upgrades and the latter should mention all the major changes since
|
||||||
the last version.
|
the last version.
|
||||||
|
|
||||||
3. Tag with:
|
2. Tag with:
|
||||||
|
|
||||||
% git tag -a 2.X
|
% git tag -a 2.X
|
||||||
|
|
||||||
@@ -157,20 +153,20 @@ Release tmux for next version
|
|||||||
|
|
||||||
Push the tag out with:
|
Push the tag out with:
|
||||||
|
|
||||||
% git push 2.X
|
% git push --tags
|
||||||
|
|
||||||
4. Build the tarball with 'make dist'.
|
3. Build the tarball with 'make dist'.
|
||||||
|
|
||||||
5. Check the tarball. If it's good, go here to select the tag just pushed:
|
4. Check the tarball. If it's good, go here to select the tag just pushed:
|
||||||
|
|
||||||
https://github.com/tmux/tmux/tags
|
https://github.com/tmux/tmux/tags
|
||||||
|
|
||||||
Click the "Add release notes", upload the tarball and add a link in the
|
Click the "Add release notes", upload the tarball and add a link in the
|
||||||
description field to the CHANGES file.
|
description field to the CHANGES file.
|
||||||
|
|
||||||
7. Clone the tmux.github.io repository, and change the RELEASE version in
|
5. Clone the tmux.github.io repository, and change the RELEASE version in the
|
||||||
the Makefile. Commit it, and run 'make' to replace %%VERSION%%. Push
|
Makefile. Commit it, and run 'make' to replace %%VERSION%%. Push the
|
||||||
the result out.
|
result out.
|
||||||
|
|
||||||
8. Bump version in tmux/tmux.git configure.ac and uncomment "enable_debug=yes" to
|
6. Bump version in tmux/tmux.git configure.ac and uncomment "enable_debug=yes"
|
||||||
create a debug build by default.
|
to create a debug build by default.
|
||||||
|
|||||||
11
TODO
11
TODO
@@ -22,6 +22,8 @@
|
|||||||
* formats to show if a window is linked into multiple sessions, into
|
* formats to show if a window is linked into multiple sessions, into
|
||||||
multiple attached sessions, and is the active window in multiple
|
multiple attached sessions, and is the active window in multiple
|
||||||
attached sessions?
|
attached sessions?
|
||||||
|
* comparison operators like < and > (for #{version}?)
|
||||||
|
* %else statement in config file
|
||||||
|
|
||||||
- choose mode improvements:
|
- choose mode improvements:
|
||||||
* choose-pane command (augment choose-tree to do this?)
|
* choose-pane command (augment choose-tree to do this?)
|
||||||
@@ -53,8 +55,9 @@
|
|||||||
then it should be found even if it is now "foo\nbar" (if the WRAP flag
|
then it should be found even if it is now "foo\nbar" (if the WRAP flag
|
||||||
is set on the line)
|
is set on the line)
|
||||||
* capture-pane option to preserve spaces but not join lines
|
* capture-pane option to preserve spaces but not join lines
|
||||||
* improve word and line selection in copy mode (for example when dragging
|
* improve word and line selection in copy mode (for example when
|
||||||
it should select by word. compare how xterm works. GitHub issue 682)
|
dragging it should select by word. compare how xterm works. GitHub
|
||||||
|
issue 682)
|
||||||
|
|
||||||
- layout stuff
|
- layout stuff
|
||||||
* way to tag a layout as a number/name
|
* way to tag a layout as a number/name
|
||||||
@@ -70,6 +73,8 @@
|
|||||||
* a mode where one application can cross two panes (ie x|y, width =
|
* a mode where one application can cross two panes (ie x|y, width =
|
||||||
COLUMNS/2 but height = ROWS * 2)
|
COLUMNS/2 but height = ROWS * 2)
|
||||||
* separate active panes for different clients
|
* separate active panes for different clients
|
||||||
|
* way to choose where the freed space goes when a pane is killed:
|
||||||
|
option to kill-pane? GitHub issue 918
|
||||||
|
|
||||||
- code cleanup
|
- code cleanup
|
||||||
* instead of separate window and session options, just one master
|
* instead of separate window and session options, just one master
|
||||||
@@ -100,7 +105,6 @@
|
|||||||
client w/o a session else cmd_current_client
|
client w/o a session else cmd_current_client
|
||||||
|
|
||||||
- miscellaneous
|
- miscellaneous
|
||||||
* way to keep a job running just read its last line of output for #()
|
|
||||||
* link panes into multiple windows
|
* link panes into multiple windows
|
||||||
* live update: server started with -U connects to server, requests
|
* live update: server started with -U connects to server, requests
|
||||||
sessions and windows, receives file descriptors
|
sessions and windows, receives file descriptors
|
||||||
@@ -113,6 +117,7 @@
|
|||||||
* marks in history, automatically add (move?) one when pane is changed
|
* marks in history, automatically add (move?) one when pane is changed
|
||||||
* this doesn't work, need pane reference count probably:
|
* this doesn't work, need pane reference count probably:
|
||||||
bind -n DoubleClick3Status confirm-before -p "kill-window #I? (y/n)" kill-window
|
bind -n DoubleClick3Status confirm-before -p "kill-window #I? (y/n)" kill-window
|
||||||
|
* respawn -c flag same as neww etc
|
||||||
|
|
||||||
- hooks
|
- hooks
|
||||||
* more hooks for various things
|
* more hooks for various things
|
||||||
|
|||||||
28
alerts.c
28
alerts.c
@@ -64,7 +64,7 @@ alerts_callback(__unused int fd, __unused short events, __unused void *arg)
|
|||||||
TAILQ_REMOVE(&alerts_list, w, alerts_entry);
|
TAILQ_REMOVE(&alerts_list, w, alerts_entry);
|
||||||
|
|
||||||
w->flags &= ~WINDOW_ALERTFLAGS;
|
w->flags &= ~WINDOW_ALERTFLAGS;
|
||||||
window_remove_ref(w);
|
window_remove_ref(w, __func__);
|
||||||
}
|
}
|
||||||
alerts_fired = 0;
|
alerts_fired = 0;
|
||||||
}
|
}
|
||||||
@@ -144,16 +144,18 @@ alerts_queue(struct window *w, int flags)
|
|||||||
log_debug("@%u alerts flags added %#x", w->id, flags);
|
log_debug("@%u alerts flags added %#x", w->id, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!w->alerts_queued) {
|
if (alerts_enabled(w, flags)) {
|
||||||
w->alerts_queued = 1;
|
if (!w->alerts_queued) {
|
||||||
TAILQ_INSERT_TAIL(&alerts_list, w, alerts_entry);
|
w->alerts_queued = 1;
|
||||||
w->references++;
|
TAILQ_INSERT_TAIL(&alerts_list, w, alerts_entry);
|
||||||
}
|
window_add_ref(w, __func__);
|
||||||
|
}
|
||||||
|
|
||||||
if (!alerts_fired && alerts_enabled(w, flags)) {
|
if (!alerts_fired) {
|
||||||
log_debug("alerts check queued (by @%u)", w->id);
|
log_debug("alerts check queued (by @%u)", w->id);
|
||||||
event_once(-1, EV_TIMEOUT, alerts_callback, NULL, NULL);
|
event_once(-1, EV_TIMEOUT, alerts_callback, NULL, NULL);
|
||||||
alerts_fired = 1;
|
alerts_fired = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,7 +180,7 @@ alerts_check_bell(struct window *w)
|
|||||||
s = wl->session;
|
s = wl->session;
|
||||||
if (s->curw != wl) {
|
if (s->curw != wl) {
|
||||||
wl->flags |= WINLINK_BELL;
|
wl->flags |= WINLINK_BELL;
|
||||||
notify_winlink("alert-bell", s, wl);
|
notify_winlink("alert-bell", wl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->flags & SESSION_ALERTED)
|
if (s->flags & SESSION_ALERTED)
|
||||||
@@ -239,7 +241,7 @@ alerts_check_activity(struct window *w)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
wl->flags |= WINLINK_ACTIVITY;
|
wl->flags |= WINLINK_ACTIVITY;
|
||||||
notify_winlink("alert-activity", s, wl);
|
notify_winlink("alert-activity", wl);
|
||||||
|
|
||||||
if (s->flags & SESSION_ALERTED)
|
if (s->flags & SESSION_ALERTED)
|
||||||
continue;
|
continue;
|
||||||
@@ -275,7 +277,7 @@ alerts_check_silence(struct window *w)
|
|||||||
if (s->curw == wl)
|
if (s->curw == wl)
|
||||||
continue;
|
continue;
|
||||||
wl->flags |= WINLINK_SILENCE;
|
wl->flags |= WINLINK_SILENCE;
|
||||||
notify_winlink("alert-silence", s, wl);
|
notify_winlink("alert-silence", wl);
|
||||||
|
|
||||||
if (s->flags & SESSION_ALERTED)
|
if (s->flags & SESSION_ALERTED)
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
54
cfg.c
54
cfg.c
@@ -27,11 +27,19 @@
|
|||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
static char *cfg_file;
|
static char *cfg_file;
|
||||||
int cfg_finished;
|
int cfg_finished;
|
||||||
static char **cfg_causes;
|
static char **cfg_causes;
|
||||||
static u_int cfg_ncauses;
|
static u_int cfg_ncauses;
|
||||||
struct client *cfg_client;
|
static struct cmdq_item *cfg_item;
|
||||||
|
|
||||||
|
static enum cmd_retval
|
||||||
|
cfg_client_done(__unused struct cmdq_item *item, __unused void *data)
|
||||||
|
{
|
||||||
|
if (!cfg_finished)
|
||||||
|
return (CMD_RETURN_WAIT);
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cfg_done(__unused struct cmdq_item *item, __unused void *data)
|
cfg_done(__unused struct cmdq_item *item, __unused void *data)
|
||||||
@@ -43,8 +51,11 @@ cfg_done(__unused struct cmdq_item *item, __unused void *data)
|
|||||||
if (!RB_EMPTY(&sessions))
|
if (!RB_EMPTY(&sessions))
|
||||||
cfg_show_causes(RB_MIN(sessions, &sessions));
|
cfg_show_causes(RB_MIN(sessions, &sessions));
|
||||||
|
|
||||||
if (cfg_client != NULL)
|
if (cfg_item != NULL)
|
||||||
server_client_unref(cfg_client);
|
cfg_item->flags &= ~CMDQ_WAITING;
|
||||||
|
|
||||||
|
status_prompt_load_history();
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,21 +71,35 @@ start_cfg(void)
|
|||||||
{
|
{
|
||||||
const char *home;
|
const char *home;
|
||||||
int quiet = 0;
|
int quiet = 0;
|
||||||
|
struct client *c;
|
||||||
|
|
||||||
cfg_client = TAILQ_FIRST(&clients);
|
/*
|
||||||
if (cfg_client != NULL)
|
* Configuration files are loaded without a client, so NULL is passed
|
||||||
cfg_client->references++;
|
* into load_cfg() and commands run in the global queue with
|
||||||
|
* item->client NULL.
|
||||||
|
*
|
||||||
|
* However, we must block the initial client (but just the initial
|
||||||
|
* client) so that its command runs after the configuration is loaded.
|
||||||
|
* Because start_cfg() is called so early, we can be sure the client's
|
||||||
|
* command queue is currently empty and our callback will be at the
|
||||||
|
* front - we need to get in before MSG_COMMAND.
|
||||||
|
*/
|
||||||
|
c = TAILQ_FIRST(&clients);
|
||||||
|
if (c != NULL) {
|
||||||
|
cfg_item = cmdq_get_callback(cfg_client_done, NULL);
|
||||||
|
cmdq_append(c, cfg_item);
|
||||||
|
}
|
||||||
|
|
||||||
load_cfg(TMUX_CONF, cfg_client, NULL, 1);
|
load_cfg(TMUX_CONF, NULL, NULL, 1);
|
||||||
|
|
||||||
if (cfg_file == NULL && (home = find_home()) != NULL) {
|
if (cfg_file == NULL && (home = find_home()) != NULL) {
|
||||||
xasprintf(&cfg_file, "%s/.tmux.conf", home);
|
xasprintf(&cfg_file, "%s/.tmux.conf", home);
|
||||||
quiet = 1;
|
quiet = 1;
|
||||||
}
|
}
|
||||||
if (cfg_file != NULL)
|
if (cfg_file != NULL)
|
||||||
load_cfg(cfg_file, cfg_client, NULL, quiet);
|
load_cfg(cfg_file, NULL, NULL, quiet);
|
||||||
|
|
||||||
cmdq_append(cfg_client, cmdq_get_callback(cfg_done, NULL));
|
cmdq_append(NULL, cmdq_get_callback(cfg_done, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -122,7 +147,8 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item, int quiet)
|
|||||||
line);
|
line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ft = format_create(NULL, FORMAT_NONE, FORMAT_NOJOBS);
|
ft = format_create(NULL, NULL, FORMAT_NONE,
|
||||||
|
FORMAT_NOJOBS);
|
||||||
|
|
||||||
s = p + 3;
|
s = p + 3;
|
||||||
while (isspace((u_char)*s))
|
while (isspace((u_char)*s))
|
||||||
|
|||||||
@@ -40,20 +40,23 @@ const struct cmd_entry cmd_attach_session_entry = {
|
|||||||
.args = { "c:dErt:", 0, 0 },
|
.args = { "c:dErt:", 0, 0 },
|
||||||
.usage = "[-dEr] [-c working-directory] " CMD_TARGET_SESSION_USAGE,
|
.usage = "[-dEr] [-c working-directory] " CMD_TARGET_SESSION_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_SESSION_WITHPANE,
|
/* -t is special */
|
||||||
|
|
||||||
.flags = CMD_STARTSERVER,
|
.flags = CMD_STARTSERVER,
|
||||||
.exec = cmd_attach_session_exec
|
.exec = cmd_attach_session_exec
|
||||||
};
|
};
|
||||||
|
|
||||||
enum cmd_retval
|
enum cmd_retval
|
||||||
cmd_attach_session(struct cmdq_item *item, int dflag, int rflag,
|
cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
|
||||||
const char *cflag, int Eflag)
|
int rflag, const char *cflag, int Eflag)
|
||||||
{
|
{
|
||||||
struct session *s = item->state.tflag.s;
|
struct cmd_find_state *current = &item->shared->current;
|
||||||
|
enum cmd_find_type type;
|
||||||
|
int flags;
|
||||||
struct client *c = item->client, *c_loop;
|
struct client *c = item->client, *c_loop;
|
||||||
struct winlink *wl = item->state.tflag.wl;
|
struct session *s;
|
||||||
struct window_pane *wp = item->state.tflag.wp;
|
struct winlink *wl;
|
||||||
|
struct window_pane *wp;
|
||||||
char *cause;
|
char *cause;
|
||||||
|
|
||||||
if (RB_EMPTY(&sessions)) {
|
if (RB_EMPTY(&sessions)) {
|
||||||
@@ -69,10 +72,27 @@ cmd_attach_session(struct cmdq_item *item, int dflag, int rflag,
|
|||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tflag != NULL && tflag[strcspn(tflag, ":.")] != '\0') {
|
||||||
|
type = CMD_FIND_PANE;
|
||||||
|
flags = 0;
|
||||||
|
} else {
|
||||||
|
type = CMD_FIND_SESSION;
|
||||||
|
flags = CMD_FIND_PREFER_UNATTACHED;
|
||||||
|
}
|
||||||
|
if (cmd_find_target(&item->target, item, tflag, type, flags) != 0)
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
s = item->target.s;
|
||||||
|
wl = item->target.wl;
|
||||||
|
wp = item->target.wp;
|
||||||
|
|
||||||
if (wl != NULL) {
|
if (wl != NULL) {
|
||||||
if (wp != NULL)
|
if (wp != NULL)
|
||||||
window_set_active_pane(wp->window, wp);
|
window_set_active_pane(wp->window, wp);
|
||||||
session_set_current(s, wl);
|
session_set_current(s, wl);
|
||||||
|
if (wp != NULL)
|
||||||
|
cmd_find_from_winlink_pane(current, wl, wp);
|
||||||
|
else
|
||||||
|
cmd_find_from_winlink(current, wl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cflag != NULL) {
|
if (cflag != NULL) {
|
||||||
@@ -92,7 +112,7 @@ cmd_attach_session(struct cmdq_item *item, int dflag, int rflag,
|
|||||||
environ_update(s->options, c->environ, s->environ);
|
environ_update(s->options, c->environ, s->environ);
|
||||||
|
|
||||||
c->session = s;
|
c->session = s;
|
||||||
if (!item->repeat)
|
if (~item->shared->flags & CMDQ_SHARED_REPEAT)
|
||||||
server_client_set_key_table(c, NULL);
|
server_client_set_key_table(c, NULL);
|
||||||
status_timer_start(c);
|
status_timer_start(c);
|
||||||
notify_client("client-session-changed", c);
|
notify_client("client-session-changed", c);
|
||||||
@@ -145,6 +165,7 @@ cmd_attach_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
|
|
||||||
return (cmd_attach_session(item, args_has(args, 'd'),
|
return (cmd_attach_session(item, args_get(args, 't'),
|
||||||
args_has(args, 'r'), args_get(args, 'c'), args_has(args, 'E')));
|
args_has(args, 'd'), args_has(args, 'r'), args_get(args, 'c'),
|
||||||
|
args_has(args, 'E')));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,10 +35,11 @@ const struct cmd_entry cmd_break_pane_entry = {
|
|||||||
.alias = "breakp",
|
.alias = "breakp",
|
||||||
|
|
||||||
.args = { "dPF:n:s:t:", 0, 0 },
|
.args = { "dPF:n:s:t:", 0, 0 },
|
||||||
.usage = "[-dP] [-F format] [-n window-name] [-s src-pane] [-t dst-window]",
|
.usage = "[-dP] [-F format] [-n window-name] [-s src-pane] "
|
||||||
|
"[-t dst-window]",
|
||||||
|
|
||||||
.sflag = CMD_PANE,
|
.source = { 's', CMD_FIND_PANE, 0 },
|
||||||
.tflag = CMD_WINDOW_INDEX,
|
.target = { 't', CMD_FIND_WINDOW, CMD_FIND_WINDOW_INDEX },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_break_pane_exec
|
.exec = cmd_break_pane_exec
|
||||||
@@ -48,14 +49,15 @@ static enum cmd_retval
|
|||||||
cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct client *c = item->state.c;
|
struct cmd_find_state *current = &item->shared->current;
|
||||||
struct winlink *wl = item->state.sflag.wl;
|
struct client *c = cmd_find_client(item, NULL, 1);
|
||||||
struct session *src_s = item->state.sflag.s;
|
struct winlink *wl = item->source.wl;
|
||||||
struct session *dst_s = item->state.tflag.s;
|
struct session *src_s = item->source.s;
|
||||||
struct window_pane *wp = item->state.sflag.wp;
|
struct session *dst_s = item->target.s;
|
||||||
|
struct window_pane *wp = item->source.wp;
|
||||||
struct window *w = wl->window;
|
struct window *w = wl->window;
|
||||||
char *name, *cause;
|
char *name, *cause;
|
||||||
int idx = item->state.tflag.idx;
|
int idx = item->target.idx;
|
||||||
const char *template;
|
const char *template;
|
||||||
char *cp;
|
char *cp;
|
||||||
|
|
||||||
@@ -93,8 +95,10 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (idx == -1)
|
if (idx == -1)
|
||||||
idx = -1 - options_get_number(dst_s->options, "base-index");
|
idx = -1 - options_get_number(dst_s->options, "base-index");
|
||||||
wl = session_attach(dst_s, w, idx, &cause); /* can't fail */
|
wl = session_attach(dst_s, w, idx, &cause); /* can't fail */
|
||||||
if (!args_has(self->args, 'd'))
|
if (!args_has(self->args, 'd')) {
|
||||||
session_select(dst_s, wl->idx);
|
session_select(dst_s, wl->idx);
|
||||||
|
cmd_find_from_session(current, dst_s);
|
||||||
|
}
|
||||||
|
|
||||||
server_redraw_session(src_s);
|
server_redraw_session(src_s);
|
||||||
if (src_s != dst_s)
|
if (src_s != dst_s)
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ const struct cmd_entry cmd_capture_pane_entry = {
|
|||||||
.usage = "[-aCeJpPq] " CMD_BUFFER_USAGE " [-E end-line] "
|
.usage = "[-aCeJpPq] " CMD_BUFFER_USAGE " [-E end-line] "
|
||||||
"[-S start-line]" CMD_TARGET_PANE_USAGE,
|
"[-S start-line]" CMD_TARGET_PANE_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_PANE,
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_capture_pane_exec
|
.exec = cmd_capture_pane_exec
|
||||||
@@ -56,7 +56,7 @@ const struct cmd_entry cmd_clear_history_entry = {
|
|||||||
.args = { "t:", 0, 0 },
|
.args = { "t:", 0, 0 },
|
||||||
.usage = CMD_TARGET_PANE_USAGE,
|
.usage = CMD_TARGET_PANE_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_PANE,
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_capture_pane_exec
|
.exec = cmd_capture_pane_exec
|
||||||
@@ -193,7 +193,7 @@ cmd_capture_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct client *c;
|
struct client *c;
|
||||||
struct window_pane *wp = item->state.tflag.wp;
|
struct window_pane *wp = item->target.wp;
|
||||||
char *buf, *cause;
|
char *buf, *cause;
|
||||||
const char *bufname;
|
const char *bufname;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ const struct cmd_entry cmd_choose_buffer_entry = {
|
|||||||
.args = { "F:t:", 0, 1 },
|
.args = { "F:t:", 0, 1 },
|
||||||
.usage = CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
|
.usage = CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
|
||||||
|
|
||||||
.tflag = CMD_WINDOW,
|
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_choose_buffer_exec
|
.exec = cmd_choose_buffer_exec
|
||||||
@@ -50,8 +50,8 @@ static enum cmd_retval
|
|||||||
cmd_choose_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_choose_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct client *c = item->state.c;
|
struct client *c = cmd_find_client(item, NULL, 1);
|
||||||
struct winlink *wl = item->state.tflag.wl;
|
struct winlink *wl = item->target.wl;
|
||||||
struct window_choose_data *cdata;
|
struct window_choose_data *cdata;
|
||||||
struct paste_buffer *pb;
|
struct paste_buffer *pb;
|
||||||
char *action, *action_data;
|
char *action, *action_data;
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ const struct cmd_entry cmd_choose_client_entry = {
|
|||||||
.args = { "F:t:", 0, 1 },
|
.args = { "F:t:", 0, 1 },
|
||||||
.usage = CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
|
.usage = CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
|
||||||
|
|
||||||
.tflag = CMD_WINDOW,
|
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_choose_client_exec
|
.exec = cmd_choose_client_exec
|
||||||
@@ -59,10 +59,10 @@ static enum cmd_retval
|
|||||||
cmd_choose_client_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_choose_client_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct client *c = item->state.c;
|
struct client *c = cmd_find_client(item, NULL, 1);
|
||||||
struct client *c1;
|
struct client *c1;
|
||||||
struct window_choose_data *cdata;
|
struct window_choose_data *cdata;
|
||||||
struct winlink *wl = item->state.tflag.wl;
|
struct winlink *wl = item->target.wl;
|
||||||
const char *template;
|
const char *template;
|
||||||
char *action;
|
char *action;
|
||||||
u_int idx, cur;
|
u_int idx, cur;
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ const struct cmd_entry cmd_choose_tree_entry = {
|
|||||||
.usage = "[-suw] [-b session-template] [-c window template] "
|
.usage = "[-suw] [-b session-template] [-c window template] "
|
||||||
"[-S format] [-W format] " CMD_TARGET_WINDOW_USAGE,
|
"[-S format] [-W format] " CMD_TARGET_WINDOW_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_WINDOW,
|
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_choose_tree_exec
|
.exec = cmd_choose_tree_exec
|
||||||
@@ -64,7 +64,7 @@ const struct cmd_entry cmd_choose_session_entry = {
|
|||||||
.args = { "F:t:", 0, 1 },
|
.args = { "F:t:", 0, 1 },
|
||||||
.usage = CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
|
.usage = CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
|
||||||
|
|
||||||
.tflag = CMD_WINDOW,
|
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_choose_tree_exec
|
.exec = cmd_choose_tree_exec
|
||||||
@@ -77,7 +77,7 @@ const struct cmd_entry cmd_choose_window_entry = {
|
|||||||
.args = { "F:t:", 0, 1 },
|
.args = { "F:t:", 0, 1 },
|
||||||
.usage = CMD_TARGET_WINDOW_USAGE "[-F format] [template]",
|
.usage = CMD_TARGET_WINDOW_USAGE "[-F format] [template]",
|
||||||
|
|
||||||
.tflag = CMD_WINDOW,
|
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_choose_tree_exec
|
.exec = cmd_choose_tree_exec
|
||||||
@@ -87,9 +87,9 @@ static enum cmd_retval
|
|||||||
cmd_choose_tree_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_choose_tree_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct client *c = item->state.c;
|
struct client *c = cmd_find_client(item, NULL, 1);
|
||||||
struct winlink *wl = item->state.tflag.wl, *wm;
|
struct winlink *wl = item->target.wl, *wm;
|
||||||
struct session *s = item->state.tflag.s, *s2;
|
struct session *s = item->target.s, *s2;
|
||||||
struct window_choose_data *wcd = NULL;
|
struct window_choose_data *wcd = NULL;
|
||||||
const char *ses_template, *win_template;
|
const char *ses_template, *win_template;
|
||||||
char *final_win_action, *cur_win_template;
|
char *final_win_action, *cur_win_template;
|
||||||
|
|||||||
@@ -43,8 +43,6 @@ const struct cmd_entry cmd_command_prompt_entry = {
|
|||||||
.usage = "[-1Ni] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " "
|
.usage = "[-1Ni] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " "
|
||||||
"[template]",
|
"[template]",
|
||||||
|
|
||||||
.tflag = CMD_CLIENT,
|
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_command_prompt_exec
|
.exec = cmd_command_prompt_exec
|
||||||
};
|
};
|
||||||
@@ -69,10 +67,13 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
const char *inputs, *prompts;
|
const char *inputs, *prompts;
|
||||||
struct cmd_command_prompt_cdata *cdata;
|
struct cmd_command_prompt_cdata *cdata;
|
||||||
struct client *c = item->state.c;
|
struct client *c;
|
||||||
char *prompt, *ptr, *input = NULL;
|
char *prompt, *ptr, *input = NULL;
|
||||||
size_t n;
|
size_t n;
|
||||||
|
|
||||||
|
if ((c = cmd_find_client(item, args_get(args, 't'), 0)) == NULL)
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
|
||||||
if (c->prompt_string != NULL)
|
if (c->prompt_string != NULL)
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
@@ -192,7 +193,7 @@ cmd_command_prompt_callback(void *data, const char *s, int done)
|
|||||||
|
|
||||||
if (!done)
|
if (!done)
|
||||||
free(new_template);
|
free(new_template);
|
||||||
if (c->prompt_callbackfn != (void *)&cmd_command_prompt_callback)
|
if (c->prompt_callbackfn != cmd_command_prompt_callback)
|
||||||
return (1);
|
return (1);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,8 +41,6 @@ const struct cmd_entry cmd_confirm_before_entry = {
|
|||||||
.args = { "p:t:", 1, 1 },
|
.args = { "p:t:", 1, 1 },
|
||||||
.usage = "[-p prompt] " CMD_TARGET_CLIENT_USAGE " command",
|
.usage = "[-p prompt] " CMD_TARGET_CLIENT_USAGE " command",
|
||||||
|
|
||||||
.tflag = CMD_CLIENT,
|
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_confirm_before_exec
|
.exec = cmd_confirm_before_exec
|
||||||
};
|
};
|
||||||
@@ -57,10 +55,13 @@ cmd_confirm_before_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct cmd_confirm_before_data *cdata;
|
struct cmd_confirm_before_data *cdata;
|
||||||
struct client *c = item->state.c;
|
struct client *c;
|
||||||
char *cmd, *copy, *new_prompt, *ptr;
|
char *cmd, *copy, *new_prompt, *ptr;
|
||||||
const char *prompt;
|
const char *prompt;
|
||||||
|
|
||||||
|
if ((c = cmd_find_client(item, args_get(args, 't'), 0)) == NULL)
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
|
||||||
if ((prompt = args_get(args, 'p')) != NULL)
|
if ((prompt = args_get(args, 'p')) != NULL)
|
||||||
xasprintf(&new_prompt, "%s ", prompt);
|
xasprintf(&new_prompt, "%s ", prompt);
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ const struct cmd_entry cmd_copy_mode_entry = {
|
|||||||
.args = { "Met:u", 0, 0 },
|
.args = { "Met:u", 0, 0 },
|
||||||
.usage = "[-Mu] " CMD_TARGET_PANE_USAGE,
|
.usage = "[-Mu] " CMD_TARGET_PANE_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_PANE,
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_copy_mode_exec
|
.exec = cmd_copy_mode_exec
|
||||||
@@ -46,7 +46,7 @@ const struct cmd_entry cmd_clock_mode_entry = {
|
|||||||
.args = { "t:", 0, 0 },
|
.args = { "t:", 0, 0 },
|
||||||
.usage = CMD_TARGET_PANE_USAGE,
|
.usage = CMD_TARGET_PANE_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_PANE,
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_copy_mode_exec
|
.exec = cmd_copy_mode_exec
|
||||||
@@ -56,12 +56,13 @@ static enum cmd_retval
|
|||||||
cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
|
struct cmdq_shared *shared = item->shared;
|
||||||
struct client *c = item->client;
|
struct client *c = item->client;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
struct window_pane *wp = item->state.tflag.wp;
|
struct window_pane *wp = item->target.wp;
|
||||||
|
|
||||||
if (args_has(args, 'M')) {
|
if (args_has(args, 'M')) {
|
||||||
if ((wp = cmd_mouse_pane(&item->mouse, &s, NULL)) == NULL)
|
if ((wp = cmd_mouse_pane(&shared->mouse, &s, NULL)) == NULL)
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
if (c == NULL || c->session != s)
|
if (c == NULL || c->session != s)
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
@@ -80,7 +81,7 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (args_has(args, 'M')) {
|
if (args_has(args, 'M')) {
|
||||||
if (wp->mode != NULL && wp->mode != &window_copy_mode)
|
if (wp->mode != NULL && wp->mode != &window_copy_mode)
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
window_copy_start_drag(c, &item->mouse);
|
window_copy_start_drag(c, &shared->mouse);
|
||||||
}
|
}
|
||||||
if (wp->mode == &window_copy_mode && args_has(self->args, 'u'))
|
if (wp->mode == &window_copy_mode && args_has(self->args, 'u'))
|
||||||
window_copy_pageup(wp, 0);
|
window_copy_pageup(wp, 0);
|
||||||
|
|||||||
@@ -37,8 +37,7 @@ const struct cmd_entry cmd_detach_client_entry = {
|
|||||||
.usage = "[-aP] [-E shell-command] "
|
.usage = "[-aP] [-E shell-command] "
|
||||||
"[-s target-session] " CMD_TARGET_CLIENT_USAGE,
|
"[-s target-session] " CMD_TARGET_CLIENT_USAGE,
|
||||||
|
|
||||||
.sflag = CMD_SESSION,
|
.source = { 's', CMD_FIND_SESSION, CMD_FIND_CANFAIL },
|
||||||
.tflag = CMD_CLIENT,
|
|
||||||
|
|
||||||
.flags = CMD_READONLY,
|
.flags = CMD_READONLY,
|
||||||
.exec = cmd_detach_client_exec
|
.exec = cmd_detach_client_exec
|
||||||
@@ -51,8 +50,6 @@ const struct cmd_entry cmd_suspend_client_entry = {
|
|||||||
.args = { "t:", 0, 0 },
|
.args = { "t:", 0, 0 },
|
||||||
.usage = CMD_TARGET_CLIENT_USAGE,
|
.usage = CMD_TARGET_CLIENT_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_CLIENT,
|
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_detach_client_exec
|
.exec = cmd_detach_client_exec
|
||||||
};
|
};
|
||||||
@@ -61,15 +58,16 @@ static enum cmd_retval
|
|||||||
cmd_detach_client_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_detach_client_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct client *c = item->state.c, *cloop;
|
struct client *c, *cloop;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
enum msgtype msgtype;
|
enum msgtype msgtype;
|
||||||
const char *cmd = args_get(args, 'E');
|
const char *cmd = args_get(args, 'E');
|
||||||
|
|
||||||
|
if ((c = cmd_find_client(item, args_get(args, 't'), 0)) == NULL)
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
|
||||||
if (self->entry == &cmd_suspend_client_entry) {
|
if (self->entry == &cmd_suspend_client_entry) {
|
||||||
tty_stop_tty(&c->tty);
|
server_client_suspend(c);
|
||||||
c->flags |= CLIENT_SUSPENDED;
|
|
||||||
proc_send(c->peer, MSG_SUSPEND, -1, NULL, 0);
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +77,9 @@ cmd_detach_client_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
msgtype = MSG_DETACH;
|
msgtype = MSG_DETACH;
|
||||||
|
|
||||||
if (args_has(args, 's')) {
|
if (args_has(args, 's')) {
|
||||||
s = item->state.sflag.s;
|
s = item->source.s;
|
||||||
|
if (s == NULL)
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
TAILQ_FOREACH(cloop, &clients, entry) {
|
TAILQ_FOREACH(cloop, &clients, entry) {
|
||||||
if (cloop->session == s) {
|
if (cloop->session == s) {
|
||||||
if (cmd != NULL)
|
if (cmd != NULL)
|
||||||
|
|||||||
@@ -43,8 +43,7 @@ const struct cmd_entry cmd_display_message_entry = {
|
|||||||
.usage = "[-p] [-c target-client] [-F format] "
|
.usage = "[-p] [-c target-client] [-F format] "
|
||||||
CMD_TARGET_PANE_USAGE " [message]",
|
CMD_TARGET_PANE_USAGE " [message]",
|
||||||
|
|
||||||
.cflag = CMD_CLIENT_CANFAIL,
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
.tflag = CMD_PANE,
|
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_display_message_exec
|
.exec = cmd_display_message_exec
|
||||||
@@ -54,10 +53,10 @@ static enum cmd_retval
|
|||||||
cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct client *c = item->state.c;
|
struct client *c;
|
||||||
struct session *s = item->state.tflag.s;
|
struct session *s = item->target.s;
|
||||||
struct winlink *wl = item->state.tflag.wl;
|
struct winlink *wl = item->target.wl;
|
||||||
struct window_pane *wp = item->state.tflag.wp;
|
struct window_pane *wp = item->target.wp;
|
||||||
const char *template;
|
const char *template;
|
||||||
char *msg;
|
char *msg;
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
@@ -66,6 +65,7 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
cmdq_error(item, "only one of -F or argument must be given");
|
cmdq_error(item, "only one of -F or argument must be given");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
c = cmd_find_client(item, args_get(args, 'c'), 1);
|
||||||
|
|
||||||
template = args_get(args, 'F');
|
template = args_get(args, 'F');
|
||||||
if (args->argc != 0)
|
if (args->argc != 0)
|
||||||
@@ -73,7 +73,7 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (template == NULL)
|
if (template == NULL)
|
||||||
template = DISPLAY_MESSAGE_TEMPLATE;
|
template = DISPLAY_MESSAGE_TEMPLATE;
|
||||||
|
|
||||||
ft = format_create(item, FORMAT_NONE, 0);
|
ft = format_create(item->client, item, FORMAT_NONE, 0);
|
||||||
format_defaults(ft, c, s, wl, wp);
|
format_defaults(ft, c, s, wl, wp);
|
||||||
|
|
||||||
msg = format_expand_time(ft, template, time(NULL));
|
msg = format_expand_time(ft, template, time(NULL));
|
||||||
|
|||||||
@@ -40,8 +40,6 @@ const struct cmd_entry cmd_display_panes_entry = {
|
|||||||
.args = { "t:", 0, 1 },
|
.args = { "t:", 0, 1 },
|
||||||
.usage = CMD_TARGET_CLIENT_USAGE,
|
.usage = CMD_TARGET_CLIENT_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_CLIENT,
|
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_display_panes_exec
|
.exec = cmd_display_panes_exec
|
||||||
};
|
};
|
||||||
@@ -50,7 +48,10 @@ static enum cmd_retval
|
|||||||
cmd_display_panes_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_display_panes_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct client *c = item->state.c;
|
struct client *c;
|
||||||
|
|
||||||
|
if ((c = cmd_find_client(item, args_get(args, 't'), 0)) == NULL)
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
|
||||||
if (c->identify_callback != NULL)
|
if (c->identify_callback != NULL)
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ const struct cmd_entry cmd_find_window_entry = {
|
|||||||
.args = { "F:CNt:T", 1, 4 },
|
.args = { "F:CNt:T", 1, 4 },
|
||||||
.usage = "[-CNT] [-F format] " CMD_TARGET_WINDOW_USAGE " match-string",
|
.usage = "[-CNT] [-F format] " CMD_TARGET_WINDOW_USAGE " match-string",
|
||||||
|
|
||||||
.tflag = CMD_WINDOW,
|
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_find_window_exec
|
.exec = cmd_find_window_exec
|
||||||
@@ -142,10 +142,11 @@ static enum cmd_retval
|
|||||||
cmd_find_window_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_find_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct client *c = item->state.c;
|
struct cmd_find_state *current = &item->shared->current;
|
||||||
|
struct client *c = cmd_find_client(item, NULL, 1);
|
||||||
struct window_choose_data *cdata;
|
struct window_choose_data *cdata;
|
||||||
struct session *s = item->state.tflag.s;
|
struct session *s = item->target.s;
|
||||||
struct winlink *wl = item->state.tflag.wl, *wm;
|
struct winlink *wl = item->target.wl, *wm;
|
||||||
struct cmd_find_window_list find_list;
|
struct cmd_find_window_list find_list;
|
||||||
struct cmd_find_window_data *find_data;
|
struct cmd_find_window_data *find_data;
|
||||||
struct cmd_find_window_data *find_data1;
|
struct cmd_find_window_data *find_data1;
|
||||||
@@ -177,8 +178,10 @@ cmd_find_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (TAILQ_NEXT(TAILQ_FIRST(&find_list), entry) == NULL) {
|
if (TAILQ_NEXT(TAILQ_FIRST(&find_list), entry) == NULL) {
|
||||||
if (session_select(s, TAILQ_FIRST(&find_list)->wl->idx) == 0)
|
if (session_select(s, TAILQ_FIRST(&find_list)->wl->idx) == 0) {
|
||||||
|
cmd_find_from_session(current, s);
|
||||||
server_redraw_session(s);
|
server_redraw_session(s);
|
||||||
|
}
|
||||||
recalculate_sizes();
|
recalculate_sizes();
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|||||||
425
cmd-find.c
425
cmd-find.c
@@ -26,19 +26,12 @@
|
|||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
static struct session *cmd_find_try_TMUX(struct client *, struct window *);
|
|
||||||
static int cmd_find_client_better(struct client *, struct client *);
|
|
||||||
static struct client *cmd_find_best_client(struct client **, u_int);
|
|
||||||
static int cmd_find_session_better(struct session *, struct session *,
|
static int cmd_find_session_better(struct session *, struct session *,
|
||||||
int);
|
int);
|
||||||
static struct session *cmd_find_best_session(struct session **, u_int, int);
|
static struct session *cmd_find_best_session(struct session **, u_int, int);
|
||||||
static int cmd_find_best_session_with_window(struct cmd_find_state *);
|
static int cmd_find_best_session_with_window(struct cmd_find_state *);
|
||||||
static int cmd_find_best_winlink_with_window(struct cmd_find_state *);
|
static int cmd_find_best_winlink_with_window(struct cmd_find_state *);
|
||||||
|
|
||||||
static int cmd_find_current_session_with_client(struct cmd_find_state *);
|
|
||||||
static int cmd_find_current_session(struct cmd_find_state *);
|
|
||||||
static struct client *cmd_find_current_client(struct cmdq_item *);
|
|
||||||
|
|
||||||
static const char *cmd_find_map_table(const char *[][2], const char *);
|
static const char *cmd_find_map_table(const char *[][2], const char *);
|
||||||
|
|
||||||
static int cmd_find_get_session(struct cmd_find_state *, const char *);
|
static int cmd_find_get_session(struct cmd_find_state *, const char *);
|
||||||
@@ -83,13 +76,12 @@ static const char *cmd_find_pane_table[][2] = {
|
|||||||
|
|
||||||
/* Get session from TMUX if present. */
|
/* Get session from TMUX if present. */
|
||||||
static struct session *
|
static struct session *
|
||||||
cmd_find_try_TMUX(struct client *c, struct window *w)
|
cmd_find_try_TMUX(struct client *c)
|
||||||
{
|
{
|
||||||
struct environ_entry *envent;
|
struct environ_entry *envent;
|
||||||
char tmp[256];
|
char tmp[256];
|
||||||
long long pid;
|
long long pid;
|
||||||
u_int session;
|
u_int session;
|
||||||
struct session *s;
|
|
||||||
|
|
||||||
envent = environ_find(c->environ, "TMUX");
|
envent = environ_find(c->environ, "TMUX");
|
||||||
if (envent == NULL)
|
if (envent == NULL)
|
||||||
@@ -99,13 +91,8 @@ cmd_find_try_TMUX(struct client *c, struct window *w)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
if (pid != getpid())
|
if (pid != getpid())
|
||||||
return (NULL);
|
return (NULL);
|
||||||
log_debug("client %p TMUX is %s (session @%u)", c, envent->value,
|
log_debug("client %p TMUX %s (session @%u)", c, envent->value, session);
|
||||||
session);
|
return (session_find_by_id(session));
|
||||||
|
|
||||||
s = session_find_by_id(session);
|
|
||||||
if (s == NULL || (w != NULL && !session_has(s, w)))
|
|
||||||
return (NULL);
|
|
||||||
return (s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is this client better? */
|
/* Is this client better? */
|
||||||
@@ -117,28 +104,23 @@ cmd_find_client_better(struct client *c, struct client *than)
|
|||||||
return (timercmp(&c->activity_time, &than->activity_time, >));
|
return (timercmp(&c->activity_time, &than->activity_time, >));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find best client from a list, or all if list is NULL. */
|
/* Find best client for session. */
|
||||||
static struct client *
|
static struct client *
|
||||||
cmd_find_best_client(struct client **clist, u_int csize)
|
cmd_find_best_client(struct session *s)
|
||||||
{
|
{
|
||||||
struct client *c_loop, *c;
|
struct client *c_loop, *c;
|
||||||
u_int i;
|
|
||||||
|
if (s->flags & SESSION_UNATTACHED)
|
||||||
|
s = NULL;
|
||||||
|
|
||||||
c = NULL;
|
c = NULL;
|
||||||
if (clist != NULL) {
|
TAILQ_FOREACH(c_loop, &clients, entry) {
|
||||||
for (i = 0; i < csize; i++) {
|
if (c_loop->session == NULL)
|
||||||
if (clist[i]->session == NULL)
|
continue;
|
||||||
continue;
|
if (s != NULL && c_loop->session != s)
|
||||||
if (cmd_find_client_better(clist[i], c))
|
continue;
|
||||||
c = clist[i];
|
if (cmd_find_client_better(c_loop, c))
|
||||||
}
|
c = c_loop;
|
||||||
} else {
|
|
||||||
TAILQ_FOREACH(c_loop, &clients, entry) {
|
|
||||||
if (c_loop->session == NULL)
|
|
||||||
continue;
|
|
||||||
if (cmd_find_client_better(c_loop, c))
|
|
||||||
c = c_loop;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return (c);
|
return (c);
|
||||||
}
|
}
|
||||||
@@ -191,12 +173,6 @@ cmd_find_best_session_with_window(struct cmd_find_state *fs)
|
|||||||
u_int ssize;
|
u_int ssize;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
|
|
||||||
if (fs->item != NULL && fs->item->client != NULL) {
|
|
||||||
fs->s = cmd_find_try_TMUX(fs->item->client, fs->w);
|
|
||||||
if (fs->s != NULL)
|
|
||||||
return (cmd_find_best_winlink_with_window(fs));
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize = 0;
|
ssize = 0;
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
RB_FOREACH(s, sessions, &sessions) {
|
||||||
if (!session_has(s, fs->w))
|
if (!session_has(s, fs->w))
|
||||||
@@ -244,146 +220,6 @@ cmd_find_best_winlink_with_window(struct cmd_find_state *fs)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find current session when we have an unattached client. */
|
|
||||||
static int
|
|
||||||
cmd_find_current_session_with_client(struct cmd_find_state *fs)
|
|
||||||
{
|
|
||||||
struct window_pane *wp;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If this is running in a pane, we can use that to limit the list of
|
|
||||||
* sessions to those containing that pane (we still use the current
|
|
||||||
* window in the best session).
|
|
||||||
*/
|
|
||||||
if (fs->item != NULL) {
|
|
||||||
RB_FOREACH(wp, window_pane_tree, &all_window_panes) {
|
|
||||||
if (strcmp(wp->tty, fs->item->client->ttyname) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
wp = NULL;
|
|
||||||
|
|
||||||
/* Not running in a pane. We know nothing. Find the best session. */
|
|
||||||
if (wp == NULL)
|
|
||||||
goto unknown_pane;
|
|
||||||
|
|
||||||
/* Find the best session and winlink containing this pane. */
|
|
||||||
fs->w = wp->window;
|
|
||||||
if (cmd_find_best_session_with_window(fs) != 0) {
|
|
||||||
if (wp != NULL) {
|
|
||||||
/*
|
|
||||||
* The window may have been destroyed but the pane
|
|
||||||
* still on all_window_panes due to something else
|
|
||||||
* holding a reference.
|
|
||||||
*/
|
|
||||||
goto unknown_pane;
|
|
||||||
}
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Use the current window and pane from this session. */
|
|
||||||
fs->wl = fs->s->curw;
|
|
||||||
fs->idx = fs->wl->idx;
|
|
||||||
fs->w = fs->wl->window;
|
|
||||||
fs->wp = fs->w->active;
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
unknown_pane:
|
|
||||||
fs->s = NULL;
|
|
||||||
if (fs->item != NULL)
|
|
||||||
fs->s = cmd_find_try_TMUX(fs->item->client, NULL);
|
|
||||||
if (fs->s == NULL)
|
|
||||||
fs->s = cmd_find_best_session(NULL, 0, fs->flags);
|
|
||||||
if (fs->s == NULL)
|
|
||||||
return (-1);
|
|
||||||
fs->wl = fs->s->curw;
|
|
||||||
fs->idx = fs->wl->idx;
|
|
||||||
fs->w = fs->wl->window;
|
|
||||||
fs->wp = fs->w->active;
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Work out the best current state. If this function succeeds, the state is
|
|
||||||
* guaranteed to be completely filled in.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
cmd_find_current_session(struct cmd_find_state *fs)
|
|
||||||
{
|
|
||||||
/* If we know the current client, use it. */
|
|
||||||
if (fs->item != NULL && fs->item->client != NULL) {
|
|
||||||
log_debug("%s: have client %p%s", __func__, fs->item->client,
|
|
||||||
fs->item->client->session == NULL ? "" : " (with session)");
|
|
||||||
if (fs->item->client->session == NULL)
|
|
||||||
return (cmd_find_current_session_with_client(fs));
|
|
||||||
fs->s = fs->item->client->session;
|
|
||||||
fs->wl = fs->s->curw;
|
|
||||||
fs->idx = fs->wl->idx;
|
|
||||||
fs->w = fs->wl->window;
|
|
||||||
fs->wp = fs->w->active;
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We know nothing, find the best session and client. */
|
|
||||||
fs->s = cmd_find_best_session(NULL, 0, fs->flags);
|
|
||||||
if (fs->s == NULL)
|
|
||||||
return (-1);
|
|
||||||
fs->wl = fs->s->curw;
|
|
||||||
fs->idx = fs->wl->idx;
|
|
||||||
fs->w = fs->wl->window;
|
|
||||||
fs->wp = fs->w->active;
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Work out the best current client. */
|
|
||||||
static struct client *
|
|
||||||
cmd_find_current_client(struct cmdq_item *item)
|
|
||||||
{
|
|
||||||
struct cmd_find_state current;
|
|
||||||
struct session *s;
|
|
||||||
struct client *c, **clist = NULL;
|
|
||||||
u_int csize;
|
|
||||||
|
|
||||||
/* If the queue client has a session, use it. */
|
|
||||||
if (item->client != NULL && item->client->session != NULL) {
|
|
||||||
log_debug("%s: using item %p client %p", __func__, item,
|
|
||||||
item->client);
|
|
||||||
return (item->client);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise find the current session. */
|
|
||||||
cmd_find_clear_state(¤t, item, 0);
|
|
||||||
if (cmd_find_current_session(¤t) != 0)
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
/* If it is attached, find the best of it's clients. */
|
|
||||||
s = current.s;
|
|
||||||
log_debug("%s: current session $%u %s", __func__, s->id, s->name);
|
|
||||||
if (~s->flags & SESSION_UNATTACHED) {
|
|
||||||
csize = 0;
|
|
||||||
TAILQ_FOREACH(c, &clients, entry) {
|
|
||||||
if (c->session != s)
|
|
||||||
continue;
|
|
||||||
clist = xreallocarray(clist, csize + 1, sizeof *clist);
|
|
||||||
clist[csize++] = c;
|
|
||||||
}
|
|
||||||
if (csize != 0) {
|
|
||||||
c = cmd_find_best_client(clist, csize);
|
|
||||||
if (c != NULL) {
|
|
||||||
free(clist);
|
|
||||||
return (c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(clist);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise pick best of all clients. */
|
|
||||||
return (cmd_find_best_client(NULL, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Maps string in table. */
|
/* Maps string in table. */
|
||||||
static const char *
|
static const char *
|
||||||
cmd_find_map_table(const char *table[][2], const char *s)
|
cmd_find_map_table(const char *table[][2], const char *s)
|
||||||
@@ -796,18 +632,16 @@ cmd_find_get_pane_with_window(struct cmd_find_state *fs, const char *pane)
|
|||||||
|
|
||||||
/* Clear state. */
|
/* Clear state. */
|
||||||
void
|
void
|
||||||
cmd_find_clear_state(struct cmd_find_state *fs, struct cmdq_item *item,
|
cmd_find_clear_state(struct cmd_find_state *fs, int flags)
|
||||||
int flags)
|
|
||||||
{
|
{
|
||||||
memset(fs, 0, sizeof *fs);
|
memset(fs, 0, sizeof *fs);
|
||||||
|
|
||||||
fs->item = item;
|
|
||||||
fs->flags = flags;
|
fs->flags = flags;
|
||||||
|
|
||||||
fs->idx = -1;
|
fs->idx = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if state is empty/ */
|
/* Check if state is empty. */
|
||||||
int
|
int
|
||||||
cmd_find_empty_state(struct cmd_find_state *fs)
|
cmd_find_empty_state(struct cmd_find_state *fs)
|
||||||
{
|
{
|
||||||
@@ -878,10 +712,10 @@ cmd_find_log_state(const char *prefix, struct cmd_find_state *fs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Find state from a session. */
|
/* Find state from a session. */
|
||||||
int
|
void
|
||||||
cmd_find_from_session(struct cmd_find_state *fs, struct session *s)
|
cmd_find_from_session(struct cmd_find_state *fs, struct session *s)
|
||||||
{
|
{
|
||||||
cmd_find_clear_state(fs, NULL, 0);
|
cmd_find_clear_state(fs, 0);
|
||||||
|
|
||||||
fs->s = s;
|
fs->s = s;
|
||||||
fs->wl = fs->s->curw;
|
fs->wl = fs->s->curw;
|
||||||
@@ -889,23 +723,20 @@ cmd_find_from_session(struct cmd_find_state *fs, struct session *s)
|
|||||||
fs->wp = fs->w->active;
|
fs->wp = fs->w->active;
|
||||||
|
|
||||||
cmd_find_log_state(__func__, fs);
|
cmd_find_log_state(__func__, fs);
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find state from a winlink. */
|
/* Find state from a winlink. */
|
||||||
int
|
void
|
||||||
cmd_find_from_winlink(struct cmd_find_state *fs, struct session *s,
|
cmd_find_from_winlink(struct cmd_find_state *fs, struct winlink *wl)
|
||||||
struct winlink *wl)
|
|
||||||
{
|
{
|
||||||
cmd_find_clear_state(fs, NULL, 0);
|
cmd_find_clear_state(fs, 0);
|
||||||
|
|
||||||
fs->s = s;
|
fs->s = wl->session;
|
||||||
fs->wl = wl;
|
fs->wl = wl;
|
||||||
fs->w = wl->window;
|
fs->w = wl->window;
|
||||||
fs->wp = wl->window->active;
|
fs->wp = wl->window->active;
|
||||||
|
|
||||||
cmd_find_log_state(__func__, fs);
|
cmd_find_log_state(__func__, fs);
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find state from a session and window. */
|
/* Find state from a session and window. */
|
||||||
@@ -913,12 +744,14 @@ int
|
|||||||
cmd_find_from_session_window(struct cmd_find_state *fs, struct session *s,
|
cmd_find_from_session_window(struct cmd_find_state *fs, struct session *s,
|
||||||
struct window *w)
|
struct window *w)
|
||||||
{
|
{
|
||||||
cmd_find_clear_state(fs, NULL, 0);
|
cmd_find_clear_state(fs, 0);
|
||||||
|
|
||||||
fs->s = s;
|
fs->s = s;
|
||||||
fs->w = w;
|
fs->w = w;
|
||||||
if (cmd_find_best_winlink_with_window(fs) != 0)
|
if (cmd_find_best_winlink_with_window(fs) != 0) {
|
||||||
|
cmd_find_clear_state(fs, 0);
|
||||||
return (-1);
|
return (-1);
|
||||||
|
}
|
||||||
fs->wp = fs->w->active;
|
fs->wp = fs->w->active;
|
||||||
|
|
||||||
cmd_find_log_state(__func__, fs);
|
cmd_find_log_state(__func__, fs);
|
||||||
@@ -929,60 +762,200 @@ cmd_find_from_session_window(struct cmd_find_state *fs, struct session *s,
|
|||||||
int
|
int
|
||||||
cmd_find_from_window(struct cmd_find_state *fs, struct window *w)
|
cmd_find_from_window(struct cmd_find_state *fs, struct window *w)
|
||||||
{
|
{
|
||||||
cmd_find_clear_state(fs, NULL, 0);
|
cmd_find_clear_state(fs, 0);
|
||||||
|
|
||||||
fs->w = w;
|
fs->w = w;
|
||||||
if (cmd_find_best_session_with_window(fs) != 0)
|
if (cmd_find_best_session_with_window(fs) != 0) {
|
||||||
|
cmd_find_clear_state(fs, 0);
|
||||||
return (-1);
|
return (-1);
|
||||||
if (cmd_find_best_winlink_with_window(fs) != 0)
|
}
|
||||||
|
if (cmd_find_best_winlink_with_window(fs) != 0) {
|
||||||
|
cmd_find_clear_state(fs, 0);
|
||||||
return (-1);
|
return (-1);
|
||||||
|
}
|
||||||
fs->wp = fs->w->active;
|
fs->wp = fs->w->active;
|
||||||
|
|
||||||
cmd_find_log_state(__func__, fs);
|
cmd_find_log_state(__func__, fs);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Find state from a winlink and pane. */
|
||||||
|
void
|
||||||
|
cmd_find_from_winlink_pane(struct cmd_find_state *fs, struct winlink *wl,
|
||||||
|
struct window_pane *wp)
|
||||||
|
{
|
||||||
|
cmd_find_clear_state(fs, 0);
|
||||||
|
|
||||||
|
fs->s = wl->session;
|
||||||
|
fs->wl = wl;
|
||||||
|
fs->idx = fs->wl->idx;
|
||||||
|
fs->w = fs->wl->window;
|
||||||
|
fs->wp = wp;
|
||||||
|
|
||||||
|
cmd_find_log_state(__func__, fs);
|
||||||
|
}
|
||||||
|
|
||||||
/* Find state from a pane. */
|
/* Find state from a pane. */
|
||||||
int
|
int
|
||||||
cmd_find_from_pane(struct cmd_find_state *fs, struct window_pane *wp)
|
cmd_find_from_pane(struct cmd_find_state *fs, struct window_pane *wp)
|
||||||
{
|
{
|
||||||
if (cmd_find_from_window(fs, wp->window) != 0)
|
if (cmd_find_from_window(fs, wp->window) != 0)
|
||||||
return (-1);
|
return (-1);
|
||||||
if (window_pane_outside(wp))
|
if (window_pane_outside(wp)) {
|
||||||
|
cmd_find_clear_state(fs, 0);
|
||||||
return (-1);
|
return (-1);
|
||||||
|
}
|
||||||
fs->wp = wp;
|
fs->wp = wp;
|
||||||
|
|
||||||
cmd_find_log_state(__func__, fs);
|
cmd_find_log_state(__func__, fs);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find current state. */
|
/* Find state from nothing. */
|
||||||
int
|
int
|
||||||
cmd_find_current(struct cmd_find_state *fs, struct cmdq_item *item, int flags)
|
cmd_find_from_nothing(struct cmd_find_state *fs)
|
||||||
{
|
{
|
||||||
cmd_find_clear_state(fs, item, flags);
|
cmd_find_clear_state(fs, 0);
|
||||||
if (cmd_find_current_session(fs) != 0) {
|
|
||||||
if (~flags & CMD_FIND_QUIET)
|
fs->s = cmd_find_best_session(NULL, 0, fs->flags);
|
||||||
cmdq_error(item, "no current session");
|
if (fs->s == NULL) {
|
||||||
|
cmd_find_clear_state(fs, 0);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
fs->wl = fs->s->curw;
|
||||||
|
fs->idx = fs->wl->idx;
|
||||||
|
fs->w = fs->wl->window;
|
||||||
|
fs->wp = fs->w->active;
|
||||||
|
|
||||||
|
cmd_find_log_state(__func__, fs);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Find state from mouse. */
|
||||||
|
int
|
||||||
|
cmd_find_from_mouse(struct cmd_find_state *fs, struct mouse_event *m)
|
||||||
|
{
|
||||||
|
cmd_find_clear_state(fs, 0);
|
||||||
|
|
||||||
|
if (!m->valid)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
fs->wp = cmd_mouse_pane(m, &fs->s, &fs->wl);
|
||||||
|
if (fs->wp == NULL) {
|
||||||
|
cmd_find_clear_state(fs, 0);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
fs->w = fs->wl->window;
|
||||||
|
|
||||||
|
cmd_find_log_state(__func__, fs);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find state from client. */
|
||||||
|
int
|
||||||
|
cmd_find_from_client(struct cmd_find_state *fs, struct client *c)
|
||||||
|
{
|
||||||
|
struct session *s;
|
||||||
|
struct winlink *wl;
|
||||||
|
struct window_pane *wp;
|
||||||
|
|
||||||
|
/* If no client, treat as from nothing. */
|
||||||
|
if (c == NULL)
|
||||||
|
return (cmd_find_from_nothing(fs));
|
||||||
|
|
||||||
|
/* If this is an attached client, all done. */
|
||||||
|
if (c->session != NULL) {
|
||||||
|
cmd_find_from_session(fs, c->session);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
cmd_find_clear_state(fs, 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this is an unattached client running in a pane, we can use that
|
||||||
|
* to limit the list of sessions to those containing that pane.
|
||||||
|
*/
|
||||||
|
RB_FOREACH(wp, window_pane_tree, &all_window_panes) {
|
||||||
|
if (strcmp(wp->tty, c->ttyname) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (wp == NULL)
|
||||||
|
goto unknown_pane;
|
||||||
|
|
||||||
|
/* If we have a session in TMUX, see if it has this pane. */
|
||||||
|
s = cmd_find_try_TMUX(c);
|
||||||
|
if (s != NULL) {
|
||||||
|
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||||
|
if (window_has_pane(wl->window, wp))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (wl != NULL) {
|
||||||
|
fs->s = s;
|
||||||
|
fs->wl = s->curw; /* use current session */
|
||||||
|
fs->w = fs->wl->window;
|
||||||
|
fs->wp = fs->w->active; /* use active pane */
|
||||||
|
|
||||||
|
cmd_find_log_state(__func__, fs);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't have a session, or it doesn't have this pane. Try all
|
||||||
|
* sessions.
|
||||||
|
*/
|
||||||
|
fs->w = wp->window;
|
||||||
|
if (cmd_find_best_session_with_window(fs) != 0) {
|
||||||
|
if (wp != NULL) {
|
||||||
|
/*
|
||||||
|
* The window may have been destroyed but the pane
|
||||||
|
* still on all_window_panes due to something else
|
||||||
|
* holding a reference.
|
||||||
|
*/
|
||||||
|
goto unknown_pane;
|
||||||
|
}
|
||||||
|
cmd_find_clear_state(fs, 0);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
fs->wl = fs->s->curw;
|
||||||
|
fs->w = fs->wl->window;
|
||||||
|
fs->wp = fs->w->active; /* use active pane */
|
||||||
|
|
||||||
|
cmd_find_log_state(__func__, fs);
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
unknown_pane:
|
||||||
|
/*
|
||||||
|
* We're not running in a known pane, but maybe this client has TMUX
|
||||||
|
* in the environment. That'd give us a session.
|
||||||
|
*/
|
||||||
|
s = cmd_find_try_TMUX(c);
|
||||||
|
if (s != NULL) {
|
||||||
|
cmd_find_from_session(fs, s);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise we need to guess. */
|
||||||
|
return (cmd_find_from_nothing(fs));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Split target into pieces and resolve for the given type. Fills in the given
|
* Split target into pieces and resolve for the given type. Fills in the given
|
||||||
* state. Returns 0 on success or -1 on error.
|
* state. Returns 0 on success or -1 on error.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
cmd_find_target(struct cmd_find_state *fs, struct cmd_find_state *current,
|
cmd_find_target(struct cmd_find_state *fs, struct cmdq_item *item,
|
||||||
struct cmdq_item *item, const char *target, enum cmd_find_type type,
|
const char *target, enum cmd_find_type type, int flags)
|
||||||
int flags)
|
|
||||||
{
|
{
|
||||||
struct mouse_event *m;
|
struct mouse_event *m;
|
||||||
|
struct cmd_find_state current;
|
||||||
char *colon, *period, *copy = NULL;
|
char *colon, *period, *copy = NULL;
|
||||||
const char *session, *window, *pane;
|
const char *session, *window, *pane;
|
||||||
int window_only = 0, pane_only = 0;
|
int window_only = 0, pane_only = 0;
|
||||||
|
|
||||||
|
/* Can fail flag implies quiet. */
|
||||||
|
if (flags & CMD_FIND_CANFAIL)
|
||||||
|
flags |= CMD_FIND_QUIET;
|
||||||
|
|
||||||
/* Log the arguments. */
|
/* Log the arguments. */
|
||||||
if (target == NULL)
|
if (target == NULL)
|
||||||
log_debug("%s: target none, type %d", __func__, type);
|
log_debug("%s: target none, type %d", __func__, type);
|
||||||
@@ -991,21 +964,21 @@ cmd_find_target(struct cmd_find_state *fs, struct cmd_find_state *current,
|
|||||||
log_debug("%s: item %p, flags %#x", __func__, item, flags);
|
log_debug("%s: item %p, flags %#x", __func__, item, flags);
|
||||||
|
|
||||||
/* Clear new state. */
|
/* Clear new state. */
|
||||||
cmd_find_clear_state(fs, item, flags);
|
cmd_find_clear_state(fs, flags);
|
||||||
|
|
||||||
/* Find current state. */
|
/* Find current state. */
|
||||||
if (server_check_marked() && (flags & CMD_FIND_DEFAULT_MARKED)) {
|
if (server_check_marked() && (flags & CMD_FIND_DEFAULT_MARKED)) {
|
||||||
fs->current = &marked_pane;
|
fs->current = &marked_pane;
|
||||||
log_debug("%s: current is marked pane", __func__);
|
log_debug("%s: current is marked pane", __func__);
|
||||||
} else if (cmd_find_valid_state(&item->current)) {
|
} else if (cmd_find_valid_state(&item->shared->current)) {
|
||||||
fs->current = &item->current;
|
fs->current = &item->shared->current;
|
||||||
log_debug("%s: current is from queue", __func__);
|
log_debug("%s: current is from queue", __func__);
|
||||||
} else {
|
} else if (cmd_find_from_client(¤t, item->client) == 0) {
|
||||||
fs->current = current;
|
fs->current = ¤t;
|
||||||
log_debug("%s: current is from argument", __func__);
|
log_debug("%s: current is from client", __func__);
|
||||||
}
|
} else
|
||||||
if (!cmd_find_empty_state(fs->current) &&
|
goto error;
|
||||||
!cmd_find_valid_state(fs->current))
|
if (!cmd_find_valid_state(fs->current))
|
||||||
fatalx("invalid current find state");
|
fatalx("invalid current find state");
|
||||||
|
|
||||||
/* An empty or NULL target is the current. */
|
/* An empty or NULL target is the current. */
|
||||||
@@ -1014,7 +987,7 @@ cmd_find_target(struct cmd_find_state *fs, struct cmd_find_state *current,
|
|||||||
|
|
||||||
/* Mouse target is a plain = or {mouse}. */
|
/* Mouse target is a plain = or {mouse}. */
|
||||||
if (strcmp(target, "=") == 0 || strcmp(target, "{mouse}") == 0) {
|
if (strcmp(target, "=") == 0 || strcmp(target, "{mouse}") == 0) {
|
||||||
m = &item->mouse;
|
m = &item->shared->mouse;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case CMD_FIND_PANE:
|
case CMD_FIND_PANE:
|
||||||
fs->wp = cmd_mouse_pane(m, &fs->s, &fs->wl);
|
fs->wp = cmd_mouse_pane(m, &fs->s, &fs->wl);
|
||||||
@@ -1125,8 +1098,8 @@ cmd_find_target(struct cmd_find_state *fs, struct cmd_find_state *current,
|
|||||||
if (pane != NULL)
|
if (pane != NULL)
|
||||||
pane = cmd_find_map_table(cmd_find_pane_table, pane);
|
pane = cmd_find_map_table(cmd_find_pane_table, pane);
|
||||||
|
|
||||||
log_debug("target %s (flags %#x): session=%s, window=%s, pane=%s",
|
log_debug("%s: target %s (flags %#x): session=%s, window=%s, pane=%s",
|
||||||
target, flags, session == NULL ? "none" : session,
|
__func__, target, flags, session == NULL ? "none" : session,
|
||||||
window == NULL ? "none" : window, pane == NULL ? "none" : pane);
|
window == NULL ? "none" : window, pane == NULL ? "none" : pane);
|
||||||
|
|
||||||
/* No pane is allowed if want an index. */
|
/* No pane is allowed if want an index. */
|
||||||
@@ -1220,6 +1193,8 @@ error:
|
|||||||
log_debug("%s: error", __func__);
|
log_debug("%s: error", __func__);
|
||||||
|
|
||||||
free(copy);
|
free(copy);
|
||||||
|
if (flags & CMD_FIND_CANFAIL)
|
||||||
|
return (0);
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
found:
|
found:
|
||||||
@@ -1250,12 +1225,20 @@ struct client *
|
|||||||
cmd_find_client(struct cmdq_item *item, const char *target, int quiet)
|
cmd_find_client(struct cmdq_item *item, const char *target, int quiet)
|
||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
|
struct session *s;
|
||||||
char *copy;
|
char *copy;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
/* A NULL argument means the current client. */
|
/* A NULL argument means the current client. */
|
||||||
if (item != NULL && target == NULL) {
|
if (target == NULL) {
|
||||||
c = cmd_find_current_client(item);
|
c = NULL;
|
||||||
|
if (item->client != NULL && item->client->session != NULL)
|
||||||
|
c = item->client;
|
||||||
|
else {
|
||||||
|
s = cmd_find_best_session(NULL, 0, CMD_FIND_QUIET);
|
||||||
|
if (s != NULL)
|
||||||
|
c = cmd_find_best_client(s);
|
||||||
|
}
|
||||||
if (c == NULL && !quiet)
|
if (c == NULL && !quiet)
|
||||||
cmdq_error(item, "no current client");
|
cmdq_error(item, "no current client");
|
||||||
log_debug("%s: no target, return %p", __func__, c);
|
log_debug("%s: no target, return %p", __func__, c);
|
||||||
|
|||||||
@@ -31,7 +31,6 @@
|
|||||||
|
|
||||||
static enum cmd_retval cmd_if_shell_exec(struct cmd *, struct cmdq_item *);
|
static enum cmd_retval cmd_if_shell_exec(struct cmd *, struct cmdq_item *);
|
||||||
|
|
||||||
static enum cmd_retval cmd_if_shell_error(struct cmdq_item *, void *);
|
|
||||||
static void cmd_if_shell_callback(struct job *);
|
static void cmd_if_shell_callback(struct job *);
|
||||||
static void cmd_if_shell_free(void *);
|
static void cmd_if_shell_free(void *);
|
||||||
|
|
||||||
@@ -43,7 +42,7 @@ const struct cmd_entry cmd_if_shell_entry = {
|
|||||||
.usage = "[-bF] " CMD_TARGET_PANE_USAGE " shell-command command "
|
.usage = "[-bF] " CMD_TARGET_PANE_USAGE " shell-command command "
|
||||||
"[command]",
|
"[command]",
|
||||||
|
|
||||||
.tflag = CMD_PANE_CANFAIL,
|
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_if_shell_exec
|
.exec = cmd_if_shell_exec
|
||||||
@@ -65,14 +64,15 @@ static enum cmd_retval
|
|||||||
cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
|
struct cmdq_shared *shared = item->shared;
|
||||||
struct cmd_if_shell_data *cdata;
|
struct cmd_if_shell_data *cdata;
|
||||||
char *shellcmd, *cmd, *cause;
|
char *shellcmd, *cmd, *cause;
|
||||||
struct cmd_list *cmdlist;
|
struct cmd_list *cmdlist;
|
||||||
struct cmdq_item *new_item;
|
struct cmdq_item *new_item;
|
||||||
struct client *c = item->state.c;
|
struct client *c = cmd_find_client(item, NULL, 1);
|
||||||
struct session *s = item->state.tflag.s;
|
struct session *s = item->target.s;
|
||||||
struct winlink *wl = item->state.tflag.wl;
|
struct winlink *wl = item->target.wl;
|
||||||
struct window_pane *wp = item->state.tflag.wp;
|
struct window_pane *wp = item->target.wp;
|
||||||
const char *cwd;
|
const char *cwd;
|
||||||
|
|
||||||
if (item->client != NULL && item->client->session == NULL)
|
if (item->client != NULL && item->client->session == NULL)
|
||||||
@@ -100,7 +100,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
}
|
}
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
new_item = cmdq_get_command(cmdlist, NULL, &item->mouse, 0);
|
new_item = cmdq_get_command(cmdlist, NULL, &shared->mouse, 0);
|
||||||
cmdq_insert_after(item, new_item);
|
cmdq_insert_after(item, new_item);
|
||||||
cmd_list_free(cmdlist);
|
cmd_list_free(cmdlist);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
@@ -119,16 +119,17 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
cdata->cmd_else = NULL;
|
cdata->cmd_else = NULL;
|
||||||
|
|
||||||
cdata->client = item->client;
|
cdata->client = item->client;
|
||||||
cdata->client->references++;
|
if (cdata->client != NULL)
|
||||||
|
cdata->client->references++;
|
||||||
|
|
||||||
if (!args_has(args, 'b'))
|
if (!args_has(args, 'b'))
|
||||||
cdata->item = item;
|
cdata->item = item;
|
||||||
else
|
else
|
||||||
cdata->item = NULL;
|
cdata->item = NULL;
|
||||||
memcpy(&cdata->mouse, &item->mouse, sizeof cdata->mouse);
|
memcpy(&cdata->mouse, &shared->mouse, sizeof cdata->mouse);
|
||||||
|
|
||||||
job_run(shellcmd, s, cwd, cmd_if_shell_callback, cmd_if_shell_free,
|
job_run(shellcmd, s, cwd, NULL, cmd_if_shell_callback,
|
||||||
cdata);
|
cmd_if_shell_free, cdata);
|
||||||
free(shellcmd);
|
free(shellcmd);
|
||||||
|
|
||||||
if (args_has(args, 'b'))
|
if (args_has(args, 'b'))
|
||||||
@@ -136,17 +137,6 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
return (CMD_RETURN_WAIT);
|
return (CMD_RETURN_WAIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum cmd_retval
|
|
||||||
cmd_if_shell_error(struct cmdq_item *item, void *data)
|
|
||||||
{
|
|
||||||
char *error = data;
|
|
||||||
|
|
||||||
cmdq_error(item, "%s", error);
|
|
||||||
free(error);
|
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cmd_if_shell_callback(struct job *job)
|
cmd_if_shell_callback(struct job *job)
|
||||||
{
|
{
|
||||||
@@ -166,10 +156,10 @@ cmd_if_shell_callback(struct job *job)
|
|||||||
|
|
||||||
cmdlist = cmd_string_parse(cmd, file, line, &cause);
|
cmdlist = cmd_string_parse(cmd, file, line, &cause);
|
||||||
if (cmdlist == NULL) {
|
if (cmdlist == NULL) {
|
||||||
if (cause != NULL)
|
if (cause != NULL && cdata->item != NULL)
|
||||||
new_item = cmdq_get_callback(cmd_if_shell_error, cause);
|
cmdq_error(cdata->item, "%s", cause);
|
||||||
else
|
free(cause);
|
||||||
new_item = NULL;
|
new_item = NULL;
|
||||||
} else {
|
} else {
|
||||||
new_item = cmdq_get_command(cmdlist, NULL, &cdata->mouse, 0);
|
new_item = cmdq_get_command(cmdlist, NULL, &cdata->mouse, 0);
|
||||||
cmd_list_free(cmdlist);
|
cmd_list_free(cmdlist);
|
||||||
@@ -192,7 +182,8 @@ cmd_if_shell_free(void *data)
|
|||||||
{
|
{
|
||||||
struct cmd_if_shell_data *cdata = data;
|
struct cmd_if_shell_data *cdata = data;
|
||||||
|
|
||||||
server_client_unref(cdata->client);
|
if (cdata->client != NULL)
|
||||||
|
server_client_unref(cdata->client);
|
||||||
|
|
||||||
free(cdata->cmd_else);
|
free(cdata->cmd_else);
|
||||||
free(cdata->cmd_if);
|
free(cdata->cmd_if);
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ const struct cmd_entry cmd_join_pane_entry = {
|
|||||||
.args = { "bdhvp:l:s:t:", 0, 0 },
|
.args = { "bdhvp:l:s:t:", 0, 0 },
|
||||||
.usage = "[-bdhv] [-p percentage|-l size] " CMD_SRCDST_PANE_USAGE,
|
.usage = "[-bdhv] [-p percentage|-l size] " CMD_SRCDST_PANE_USAGE,
|
||||||
|
|
||||||
.sflag = CMD_PANE_MARKED,
|
.source = { 's', CMD_FIND_PANE, CMD_FIND_DEFAULT_MARKED },
|
||||||
.tflag = CMD_PANE,
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_join_pane_exec
|
.exec = cmd_join_pane_exec
|
||||||
@@ -51,8 +51,8 @@ const struct cmd_entry cmd_move_pane_entry = {
|
|||||||
.args = { "bdhvp:l:s:t:", 0, 0 },
|
.args = { "bdhvp:l:s:t:", 0, 0 },
|
||||||
.usage = "[-bdhv] [-p percentage|-l size] " CMD_SRCDST_PANE_USAGE,
|
.usage = "[-bdhv] [-p percentage|-l size] " CMD_SRCDST_PANE_USAGE,
|
||||||
|
|
||||||
.sflag = CMD_PANE,
|
.source = { 's', CMD_FIND_PANE, 0 },
|
||||||
.tflag = CMD_PANE,
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_join_pane_exec
|
.exec = cmd_join_pane_exec
|
||||||
@@ -62,6 +62,7 @@ static enum cmd_retval
|
|||||||
cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
|
struct cmd_find_state *current = &item->shared->current;
|
||||||
struct session *dst_s;
|
struct session *dst_s;
|
||||||
struct winlink *src_wl, *dst_wl;
|
struct winlink *src_wl, *dst_wl;
|
||||||
struct window *src_w, *dst_w;
|
struct window *src_w, *dst_w;
|
||||||
@@ -77,15 +78,15 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
else
|
else
|
||||||
not_same_window = 0;
|
not_same_window = 0;
|
||||||
|
|
||||||
dst_s = item->state.tflag.s;
|
dst_s = item->target.s;
|
||||||
dst_wl = item->state.tflag.wl;
|
dst_wl = item->target.wl;
|
||||||
dst_wp = item->state.tflag.wp;
|
dst_wp = item->target.wp;
|
||||||
dst_w = dst_wl->window;
|
dst_w = dst_wl->window;
|
||||||
dst_idx = dst_wl->idx;
|
dst_idx = dst_wl->idx;
|
||||||
server_unzoom_window(dst_w);
|
server_unzoom_window(dst_w);
|
||||||
|
|
||||||
src_wl = item->state.sflag.wl;
|
src_wl = item->source.wl;
|
||||||
src_wp = item->state.sflag.wp;
|
src_wp = item->source.wp;
|
||||||
src_w = src_wl->window;
|
src_w = src_wl->window;
|
||||||
server_unzoom_window(src_w);
|
server_unzoom_window(src_w);
|
||||||
|
|
||||||
@@ -145,6 +146,7 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (!args_has(args, 'd')) {
|
if (!args_has(args, 'd')) {
|
||||||
window_set_active_pane(dst_w, src_wp);
|
window_set_active_pane(dst_w, src_wp);
|
||||||
session_select(dst_s, dst_idx);
|
session_select(dst_s, dst_idx);
|
||||||
|
cmd_find_from_session(current, dst_s);
|
||||||
server_redraw_session(dst_s);
|
server_redraw_session(dst_s);
|
||||||
} else
|
} else
|
||||||
server_status_session(dst_s);
|
server_status_session(dst_s);
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ const struct cmd_entry cmd_kill_pane_entry = {
|
|||||||
.args = { "at:", 0, 0 },
|
.args = { "at:", 0, 0 },
|
||||||
.usage = "[-a] " CMD_TARGET_PANE_USAGE,
|
.usage = "[-a] " CMD_TARGET_PANE_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_PANE,
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_kill_pane_exec
|
.exec = cmd_kill_pane_exec
|
||||||
@@ -44,8 +44,8 @@ const struct cmd_entry cmd_kill_pane_entry = {
|
|||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_kill_pane_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_kill_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct winlink *wl = item->state.tflag.wl;
|
struct winlink *wl = item->target.wl;
|
||||||
struct window_pane *loopwp, *tmpwp, *wp = item->state.tflag.wp;
|
struct window_pane *loopwp, *tmpwp, *wp = item->target.wp;
|
||||||
|
|
||||||
server_unzoom_window(wl->window);
|
server_unzoom_window(wl->window);
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const struct cmd_entry cmd_kill_session_entry = {
|
|||||||
.args = { "aCt:", 0, 0 },
|
.args = { "aCt:", 0, 0 },
|
||||||
.usage = "[-aC] " CMD_TARGET_SESSION_USAGE,
|
.usage = "[-aC] " CMD_TARGET_SESSION_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_SESSION,
|
.target = { 't', CMD_FIND_SESSION, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_kill_session_exec
|
.exec = cmd_kill_session_exec
|
||||||
@@ -49,7 +49,7 @@ cmd_kill_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct session *s, *sloop, *stmp;
|
struct session *s, *sloop, *stmp;
|
||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
|
|
||||||
s = item->state.tflag.s;
|
s = item->target.s;
|
||||||
|
|
||||||
if (args_has(args, 'C')) {
|
if (args_has(args, 'C')) {
|
||||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ const struct cmd_entry cmd_kill_window_entry = {
|
|||||||
.args = { "at:", 0, 0 },
|
.args = { "at:", 0, 0 },
|
||||||
.usage = "[-a] " CMD_TARGET_WINDOW_USAGE,
|
.usage = "[-a] " CMD_TARGET_WINDOW_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_WINDOW,
|
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_kill_window_exec
|
.exec = cmd_kill_window_exec
|
||||||
@@ -46,7 +46,7 @@ const struct cmd_entry cmd_unlink_window_entry = {
|
|||||||
.args = { "kt:", 0, 0 },
|
.args = { "kt:", 0, 0 },
|
||||||
.usage = "[-k] " CMD_TARGET_WINDOW_USAGE,
|
.usage = "[-k] " CMD_TARGET_WINDOW_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_WINDOW,
|
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_kill_window_exec
|
.exec = cmd_kill_window_exec
|
||||||
@@ -56,9 +56,9 @@ static enum cmd_retval
|
|||||||
cmd_kill_window_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_kill_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct winlink *wl = item->state.tflag.wl, *wl2, *wl3;
|
struct winlink *wl = item->target.wl, *wl2, *wl3;
|
||||||
struct window *w = wl->window;
|
struct window *w = wl->window;
|
||||||
struct session *s = item->state.tflag.s;
|
struct session *s = item->target.s;
|
||||||
|
|
||||||
if (self->entry == &cmd_unlink_window_entry) {
|
if (self->entry == &cmd_unlink_window_entry) {
|
||||||
if (!args_has(self->args, 'k') && !session_is_linked(s, w)) {
|
if (!args_has(self->args, 'k') && !session_is_linked(s, w)) {
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ cmd_list_buffers_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
|
|
||||||
pb = NULL;
|
pb = NULL;
|
||||||
while ((pb = paste_walk(pb)) != NULL) {
|
while ((pb = paste_walk(pb)) != NULL) {
|
||||||
ft = format_create(item, FORMAT_NONE, 0);
|
ft = format_create(item->client, item, FORMAT_NONE, 0);
|
||||||
format_defaults_paste_buffer(ft, pb);
|
format_defaults_paste_buffer(ft, pb);
|
||||||
|
|
||||||
line = format_expand(ft, template);
|
line = format_expand(ft, template);
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ const struct cmd_entry cmd_list_clients_entry = {
|
|||||||
.args = { "F:t:", 0, 0 },
|
.args = { "F:t:", 0, 0 },
|
||||||
.usage = "[-F format] " CMD_TARGET_SESSION_USAGE,
|
.usage = "[-F format] " CMD_TARGET_SESSION_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_SESSION,
|
.target = { 't', CMD_FIND_SESSION, 0 },
|
||||||
|
|
||||||
.flags = CMD_READONLY|CMD_AFTERHOOK,
|
.flags = CMD_READONLY|CMD_AFTERHOOK,
|
||||||
.exec = cmd_list_clients_exec
|
.exec = cmd_list_clients_exec
|
||||||
@@ -60,7 +60,7 @@ cmd_list_clients_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
char *line;
|
char *line;
|
||||||
|
|
||||||
if (args_has(args, 't'))
|
if (args_has(args, 't'))
|
||||||
s = item->state.tflag.s;
|
s = item->target.s;
|
||||||
else
|
else
|
||||||
s = NULL;
|
s = NULL;
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ cmd_list_clients_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (c->session == NULL || (s != NULL && s != c->session))
|
if (c->session == NULL || (s != NULL && s != c->session))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ft = format_create(item, FORMAT_NONE, 0);
|
ft = format_create(item->client, item, FORMAT_NONE, 0);
|
||||||
format_add(ft, "line", "%u", idx);
|
format_add(ft, "line", "%u", idx);
|
||||||
format_defaults(ft, c, NULL, NULL, NULL);
|
format_defaults(ft, c, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
RB_FOREACH(bd, key_bindings, &table->key_bindings) {
|
RB_FOREACH(bd, key_bindings, &table->key_bindings) {
|
||||||
key = key_string_lookup_key(bd->key);
|
key = key_string_lookup_key(bd->key);
|
||||||
|
|
||||||
if (bd->can_repeat)
|
if (bd->flags & KEY_BINDING_REPEAT)
|
||||||
repeat = 1;
|
repeat = 1;
|
||||||
|
|
||||||
width = utf8_cstrwidth(table->name);
|
width = utf8_cstrwidth(table->name);
|
||||||
@@ -101,7 +101,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
|
|
||||||
if (!repeat)
|
if (!repeat)
|
||||||
r = "";
|
r = "";
|
||||||
else if (bd->can_repeat)
|
else if (bd->flags & KEY_BINDING_REPEAT)
|
||||||
r = "-r ";
|
r = "-r ";
|
||||||
else
|
else
|
||||||
r = " ";
|
r = " ";
|
||||||
@@ -144,7 +144,7 @@ cmd_list_keys_commands(struct cmd *self, struct cmdq_item *item)
|
|||||||
"#{command_list_usage}";
|
"#{command_list_usage}";
|
||||||
}
|
}
|
||||||
|
|
||||||
ft = format_create(item, FORMAT_NONE, 0);
|
ft = format_create(item->client, item, FORMAT_NONE, 0);
|
||||||
format_defaults(ft, NULL, NULL, NULL, NULL);
|
format_defaults(ft, NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
for (entryp = cmd_table; *entryp != NULL; entryp++) {
|
for (entryp = cmd_table; *entryp != NULL; entryp++) {
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ const struct cmd_entry cmd_list_panes_entry = {
|
|||||||
.args = { "asF:t:", 0, 0 },
|
.args = { "asF:t:", 0, 0 },
|
||||||
.usage = "[-as] [-F format] " CMD_TARGET_WINDOW_USAGE,
|
.usage = "[-as] [-F format] " CMD_TARGET_WINDOW_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_WINDOW,
|
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_list_panes_exec
|
.exec = cmd_list_panes_exec
|
||||||
@@ -51,8 +51,8 @@ static enum cmd_retval
|
|||||||
cmd_list_panes_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_list_panes_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct session *s = item->state.tflag.s;
|
struct session *s = item->target.s;
|
||||||
struct winlink *wl = item->state.tflag.wl;
|
struct winlink *wl = item->target.wl;
|
||||||
|
|
||||||
if (args_has(args, 'a'))
|
if (args_has(args, 'a'))
|
||||||
cmd_list_panes_server(self, item);
|
cmd_list_panes_server(self, item);
|
||||||
@@ -123,7 +123,7 @@ cmd_list_panes_window(struct cmd *self, struct session *s, struct winlink *wl,
|
|||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
|
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
|
||||||
ft = format_create(item, FORMAT_NONE, 0);
|
ft = format_create(item->client, item, FORMAT_NONE, 0);
|
||||||
format_add(ft, "line", "%u", n);
|
format_add(ft, "line", "%u", n);
|
||||||
format_defaults(ft, NULL, s, wl, wp);
|
format_defaults(ft, NULL, s, wl, wp);
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ cmd_list_sessions_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
RB_FOREACH(s, sessions, &sessions) {
|
RB_FOREACH(s, sessions, &sessions) {
|
||||||
ft = format_create(item, FORMAT_NONE, 0);
|
ft = format_create(item->client, item, FORMAT_NONE, 0);
|
||||||
format_add(ft, "line", "%u", n);
|
format_add(ft, "line", "%u", n);
|
||||||
format_defaults(ft, NULL, s, NULL, NULL);
|
format_defaults(ft, NULL, s, NULL, NULL);
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ const struct cmd_entry cmd_list_windows_entry = {
|
|||||||
.args = { "F:at:", 0, 0 },
|
.args = { "F:at:", 0, 0 },
|
||||||
.usage = "[-a] [-F format] " CMD_TARGET_SESSION_USAGE,
|
.usage = "[-a] [-F format] " CMD_TARGET_SESSION_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_SESSION,
|
.target = { 't', CMD_FIND_SESSION, 0 },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_list_windows_exec
|
.exec = cmd_list_windows_exec
|
||||||
@@ -66,7 +66,7 @@ cmd_list_windows_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (args_has(args, 'a'))
|
if (args_has(args, 'a'))
|
||||||
cmd_list_windows_server(self, item);
|
cmd_list_windows_server(self, item);
|
||||||
else
|
else
|
||||||
cmd_list_windows_session(self, item->state.tflag.s, item, 0);
|
cmd_list_windows_session(self, item->target.s, item, 0);
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,7 @@ cmd_list_windows_session(struct cmd *self, struct session *s,
|
|||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
u_int n;
|
u_int n;
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
const char *template;
|
const char *template;
|
||||||
char *line;
|
char *line;
|
||||||
@@ -105,7 +105,7 @@ cmd_list_windows_session(struct cmd *self, struct session *s,
|
|||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
RB_FOREACH(wl, winlinks, &s->windows) {
|
RB_FOREACH(wl, winlinks, &s->windows) {
|
||||||
ft = format_create(item, FORMAT_NONE, 0);
|
ft = format_create(item->client, item, FORMAT_NONE, 0);
|
||||||
format_add(ft, "line", "%u", n);
|
format_add(ft, "line", "%u", n);
|
||||||
format_defaults(ft, NULL, s, wl, NULL);
|
format_defaults(ft, NULL, s, wl, NULL);
|
||||||
|
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ error:
|
|||||||
free(pdata);
|
free(pdata);
|
||||||
if (f != NULL)
|
if (f != NULL)
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
free(file);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ const struct cmd_entry cmd_lock_session_entry = {
|
|||||||
.args = { "t:", 0, 0 },
|
.args = { "t:", 0, 0 },
|
||||||
.usage = CMD_TARGET_SESSION_USAGE,
|
.usage = CMD_TARGET_SESSION_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_SESSION,
|
.target = { 't', CMD_FIND_SESSION, 0 },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_lock_server_exec
|
.exec = cmd_lock_server_exec
|
||||||
@@ -57,22 +57,25 @@ const struct cmd_entry cmd_lock_client_entry = {
|
|||||||
.args = { "t:", 0, 0 },
|
.args = { "t:", 0, 0 },
|
||||||
.usage = CMD_TARGET_CLIENT_USAGE,
|
.usage = CMD_TARGET_CLIENT_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_CLIENT,
|
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_lock_server_exec
|
.exec = cmd_lock_server_exec
|
||||||
};
|
};
|
||||||
|
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_lock_server_exec(struct cmd *self, __unused struct cmdq_item *item)
|
cmd_lock_server_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
|
struct args *args = self->args;
|
||||||
|
struct client *c;
|
||||||
|
|
||||||
if (self->entry == &cmd_lock_server_entry)
|
if (self->entry == &cmd_lock_server_entry)
|
||||||
server_lock();
|
server_lock();
|
||||||
else if (self->entry == &cmd_lock_session_entry)
|
else if (self->entry == &cmd_lock_session_entry)
|
||||||
server_lock_session(item->state.tflag.s);
|
server_lock_session(item->target.s);
|
||||||
else
|
else {
|
||||||
server_lock_client(item->state.c);
|
if ((c = cmd_find_client(item, args_get(args, 't'), 0)) == NULL)
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
server_lock_client(c);
|
||||||
|
}
|
||||||
recalculate_sizes();
|
recalculate_sizes();
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ const struct cmd_entry cmd_move_window_entry = {
|
|||||||
.args = { "adkrs:t:", 0, 0 },
|
.args = { "adkrs:t:", 0, 0 },
|
||||||
.usage = "[-dkr] " CMD_SRCDST_WINDOW_USAGE,
|
.usage = "[-dkr] " CMD_SRCDST_WINDOW_USAGE,
|
||||||
|
|
||||||
.sflag = CMD_WINDOW,
|
.source = { 's', CMD_FIND_WINDOW, 0 },
|
||||||
.tflag = CMD_MOVEW_R,
|
/* -t is special */
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_move_window_exec
|
.exec = cmd_move_window_exec
|
||||||
@@ -49,8 +49,8 @@ const struct cmd_entry cmd_link_window_entry = {
|
|||||||
.args = { "adks:t:", 0, 0 },
|
.args = { "adks:t:", 0, 0 },
|
||||||
.usage = "[-dk] " CMD_SRCDST_WINDOW_USAGE,
|
.usage = "[-dk] " CMD_SRCDST_WINDOW_USAGE,
|
||||||
|
|
||||||
.sflag = CMD_WINDOW,
|
.source = { 's', CMD_FIND_WINDOW, 0 },
|
||||||
.tflag = CMD_WINDOW_INDEX,
|
/* -t is special */
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_move_window_exec
|
.exec = cmd_move_window_exec
|
||||||
@@ -60,18 +60,31 @@ static enum cmd_retval
|
|||||||
cmd_move_window_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_move_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct session *src = item->state.sflag.s;
|
const char *tflag = args_get(args, 't');
|
||||||
struct session *dst = item->state.tflag.s;
|
struct session *src;
|
||||||
struct winlink *wl = item->state.sflag.wl;
|
struct session *dst;
|
||||||
|
struct winlink *wl;
|
||||||
char *cause;
|
char *cause;
|
||||||
int idx = item->state.tflag.idx, kflag, dflag, sflag;
|
int idx, kflag, dflag, sflag;
|
||||||
|
|
||||||
if (args_has(args, 'r')) {
|
if (args_has(args, 'r')) {
|
||||||
session_renumber_windows(dst);
|
if (cmd_find_target(&item->target, item, tflag,
|
||||||
|
CMD_FIND_SESSION, CMD_FIND_QUIET) != 0)
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
|
||||||
|
session_renumber_windows(item->target.s);
|
||||||
recalculate_sizes();
|
recalculate_sizes();
|
||||||
|
server_status_session(item->target.s);
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
if (cmd_find_target(&item->target, item, tflag, CMD_FIND_WINDOW,
|
||||||
|
CMD_FIND_WINDOW_INDEX) != 0)
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
src = item->source.s;
|
||||||
|
dst = item->target.s;
|
||||||
|
wl = item->source.wl;
|
||||||
|
idx = item->target.idx;
|
||||||
|
|
||||||
kflag = args_has(self->args, 'k');
|
kflag = args_has(self->args, 'k');
|
||||||
dflag = args_has(self->args, 'd');
|
dflag = args_has(self->args, 'd');
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ const struct cmd_entry cmd_new_session_entry = {
|
|||||||
"[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] "
|
"[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] "
|
||||||
"[-y height] [command]",
|
"[-y height] [command]",
|
||||||
|
|
||||||
.tflag = CMD_SESSION_CANFAIL,
|
.target = { 't', CMD_FIND_SESSION, CMD_FIND_CANFAIL },
|
||||||
|
|
||||||
.flags = CMD_STARTSERVER,
|
.flags = CMD_STARTSERVER,
|
||||||
.exec = cmd_new_session_exec
|
.exec = cmd_new_session_exec
|
||||||
@@ -57,7 +57,7 @@ const struct cmd_entry cmd_has_session_entry = {
|
|||||||
.args = { "t:", 0, 0 },
|
.args = { "t:", 0, 0 },
|
||||||
.usage = CMD_TARGET_SESSION_USAGE,
|
.usage = CMD_TARGET_SESSION_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_SESSION,
|
.target = { 't', CMD_FIND_SESSION, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_new_session_exec
|
.exec = cmd_new_session_exec
|
||||||
@@ -83,8 +83,8 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
|
|
||||||
if (self->entry == &cmd_has_session_entry) {
|
if (self->entry == &cmd_has_session_entry) {
|
||||||
/*
|
/*
|
||||||
* cmd_prepare() will fail if the session cannot be found,
|
* cmd_find_target() will fail if the session cannot be found,
|
||||||
* hence always return success here.
|
* so always return success here.
|
||||||
*/
|
*/
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
@@ -102,16 +102,9 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
}
|
}
|
||||||
if ((as = session_find(newname)) != NULL) {
|
if ((as = session_find(newname)) != NULL) {
|
||||||
if (args_has(args, 'A')) {
|
if (args_has(args, 'A')) {
|
||||||
/*
|
|
||||||
* This item is now destined for
|
|
||||||
* attach-session. Because attach-session will
|
|
||||||
* have already been prepared, copy this
|
|
||||||
* session into its tflag so it can be used.
|
|
||||||
*/
|
|
||||||
cmd_find_from_session(&item->state.tflag, as);
|
|
||||||
return (cmd_attach_session(item,
|
return (cmd_attach_session(item,
|
||||||
args_has(args, 'D'), 0, NULL,
|
newname, args_has(args, 'D'),
|
||||||
args_has(args, 'E')));
|
0, NULL, args_has(args, 'E')));
|
||||||
}
|
}
|
||||||
cmdq_error(item, "duplicate session: %s", newname);
|
cmdq_error(item, "duplicate session: %s", newname);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
@@ -121,7 +114,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
/* Is this going to be part of a session group? */
|
/* Is this going to be part of a session group? */
|
||||||
group = args_get(args, 't');
|
group = args_get(args, 't');
|
||||||
if (group != NULL) {
|
if (group != NULL) {
|
||||||
groupwith = item->state.tflag.s;
|
groupwith = item->target.s;
|
||||||
if (groupwith == NULL) {
|
if (groupwith == NULL) {
|
||||||
if (!session_check_name(group)) {
|
if (!session_check_name(group)) {
|
||||||
cmdq_error(item, "bad group name: %s", group);
|
cmdq_error(item, "bad group name: %s", group);
|
||||||
@@ -297,7 +290,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
} else if (c->session != NULL)
|
} else if (c->session != NULL)
|
||||||
c->last_session = c->session;
|
c->last_session = c->session;
|
||||||
c->session = s;
|
c->session = s;
|
||||||
if (!item->repeat)
|
if (~item->shared->flags & CMDQ_SHARED_REPEAT)
|
||||||
server_client_set_key_table(c, NULL);
|
server_client_set_key_table(c, NULL);
|
||||||
status_timer_start(c);
|
status_timer_start(c);
|
||||||
notify_client("client-session-changed", c);
|
notify_client("client-session-changed", c);
|
||||||
@@ -324,8 +317,10 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
free(cp);
|
free(cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!detached)
|
if (!detached) {
|
||||||
c->flags |= CLIENT_ATTACHED;
|
c->flags |= CLIENT_ATTACHED;
|
||||||
|
cmd_find_from_session(&item->shared->current, s);
|
||||||
|
}
|
||||||
|
|
||||||
if (to_free != NULL)
|
if (to_free != NULL)
|
||||||
free((void *)to_free);
|
free((void *)to_free);
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ const struct cmd_entry cmd_new_window_entry = {
|
|||||||
.usage = "[-adkP] [-c start-directory] [-F format] [-n window-name] "
|
.usage = "[-adkP] [-c start-directory] [-F format] [-n window-name] "
|
||||||
CMD_TARGET_WINDOW_USAGE " [command]",
|
CMD_TARGET_WINDOW_USAGE " [command]",
|
||||||
|
|
||||||
.tflag = CMD_WINDOW_INDEX,
|
.target = { 't', CMD_FIND_WINDOW, CMD_FIND_WINDOW_INDEX },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_new_window_exec
|
.exec = cmd_new_window_exec
|
||||||
@@ -52,10 +52,11 @@ static enum cmd_retval
|
|||||||
cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct session *s = item->state.tflag.s;
|
struct cmd_find_state *current = &item->shared->current;
|
||||||
struct winlink *wl = item->state.tflag.wl;
|
struct session *s = item->target.s;
|
||||||
struct client *c = item->state.c;
|
struct winlink *wl = item->target.wl;
|
||||||
int idx = item->state.tflag.idx;
|
struct client *c = cmd_find_client(item, NULL, 1);
|
||||||
|
int idx = item->target.idx;
|
||||||
const char *cmd, *path, *template, *cwd, *to_free;
|
const char *cmd, *path, *template, *cwd, *to_free;
|
||||||
char **argv, *cause, *cp;
|
char **argv, *cause, *cp;
|
||||||
int argc, detached;
|
int argc, detached;
|
||||||
@@ -132,6 +133,7 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
}
|
}
|
||||||
if (!detached) {
|
if (!detached) {
|
||||||
session_select(s, wl->idx);
|
session_select(s, wl->idx);
|
||||||
|
cmd_find_from_winlink(current, wl);
|
||||||
server_redraw_session_group(s);
|
server_redraw_session_group(s);
|
||||||
} else
|
} else
|
||||||
server_status_session_group(s);
|
server_status_session_group(s);
|
||||||
@@ -147,7 +149,7 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (to_free != NULL)
|
if (to_free != NULL)
|
||||||
free((void *)to_free);
|
free((void *)to_free);
|
||||||
|
|
||||||
cmd_find_from_winlink(&fs, s, wl);
|
cmd_find_from_winlink(&fs, wl);
|
||||||
hooks_insert(s->hooks, item, &fs, "after-new-window");
|
hooks_insert(s->hooks, item, &fs, "after-new-window");
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ const struct cmd_entry cmd_paste_buffer_entry = {
|
|||||||
.usage = "[-dpr] [-s separator] " CMD_BUFFER_USAGE " "
|
.usage = "[-dpr] [-s separator] " CMD_BUFFER_USAGE " "
|
||||||
CMD_TARGET_PANE_USAGE,
|
CMD_TARGET_PANE_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_PANE,
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_paste_buffer_exec
|
.exec = cmd_paste_buffer_exec
|
||||||
@@ -47,7 +47,7 @@ static enum cmd_retval
|
|||||||
cmd_paste_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_paste_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct window_pane *wp = item->state.tflag.wp;
|
struct window_pane *wp = item->target.wp;
|
||||||
struct paste_buffer *pb;
|
struct paste_buffer *pb;
|
||||||
const char *sepstr, *bufname, *bufdata, *bufend, *line;
|
const char *sepstr, *bufname, *bufdata, *bufend, *line;
|
||||||
size_t seplen, bufsize;
|
size_t seplen, bufsize;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ const struct cmd_entry cmd_pipe_pane_entry = {
|
|||||||
.args = { "ot:", 0, 1 },
|
.args = { "ot:", 0, 1 },
|
||||||
.usage = "[-o] " CMD_TARGET_PANE_USAGE " [command]",
|
.usage = "[-o] " CMD_TARGET_PANE_USAGE " [command]",
|
||||||
|
|
||||||
.tflag = CMD_PANE,
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_pipe_pane_exec
|
.exec = cmd_pipe_pane_exec
|
||||||
@@ -53,10 +53,10 @@ static enum cmd_retval
|
|||||||
cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct client *c = item->state.c;
|
struct client *c = cmd_find_client(item, NULL, 1);
|
||||||
struct window_pane *wp = item->state.tflag.wp;
|
struct window_pane *wp = item->target.wp;
|
||||||
struct session *s = item->state.tflag.s;
|
struct session *s = item->target.s;
|
||||||
struct winlink *wl = item->state.tflag.wl;
|
struct winlink *wl = item->target.wl;
|
||||||
char *cmd;
|
char *cmd;
|
||||||
int old_fd, pipe_fd[2], null_fd;
|
int old_fd, pipe_fd[2], null_fd;
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
@@ -89,7 +89,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Expand the command. */
|
/* Expand the command. */
|
||||||
ft = format_create(item, FORMAT_NONE, 0);
|
ft = format_create(item->client, item, FORMAT_NONE, 0);
|
||||||
format_defaults(ft, c, s, wl, wp);
|
format_defaults(ft, c, s, wl, wp);
|
||||||
cmd = format_expand_time(ft, args->argv[0], time(NULL));
|
cmd = format_expand_time(ft, args->argv[0], time(NULL));
|
||||||
format_free(ft);
|
format_free(ft);
|
||||||
|
|||||||
91
cmd-queue.c
91
cmd-queue.c
@@ -102,8 +102,11 @@ cmdq_insert_after(struct cmdq_item *after, struct cmdq_item *item)
|
|||||||
static void
|
static void
|
||||||
cmdq_remove(struct cmdq_item *item)
|
cmdq_remove(struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
if (item->formats != NULL)
|
if (item->shared != NULL && --item->shared->references == 0) {
|
||||||
format_free(item->formats);
|
if (item->shared->formats != NULL)
|
||||||
|
format_free(item->shared->formats);
|
||||||
|
free(item->shared);
|
||||||
|
}
|
||||||
|
|
||||||
if (item->client != NULL)
|
if (item->client != NULL)
|
||||||
server_client_unref(item->client);
|
server_client_unref(item->client);
|
||||||
@@ -150,6 +153,15 @@ cmdq_get_command(struct cmd_list *cmdlist, struct cmd_find_state *current,
|
|||||||
struct cmd *cmd;
|
struct cmd *cmd;
|
||||||
u_int group = cmdq_next_group();
|
u_int group = cmdq_next_group();
|
||||||
char *tmp;
|
char *tmp;
|
||||||
|
struct cmdq_shared *shared;
|
||||||
|
|
||||||
|
shared = xcalloc(1, sizeof *shared);
|
||||||
|
if (current != NULL)
|
||||||
|
cmd_find_copy_state(&shared->current, current);
|
||||||
|
else
|
||||||
|
cmd_find_clear_state(&shared->current, 0);
|
||||||
|
if (m != NULL)
|
||||||
|
memcpy(&shared->mouse, m, sizeof shared->mouse);
|
||||||
|
|
||||||
TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
|
TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
|
||||||
xasprintf(&tmp, "command[%s]", cmd->entry->name);
|
xasprintf(&tmp, "command[%s]", cmd->entry->name);
|
||||||
@@ -161,13 +173,11 @@ cmdq_get_command(struct cmd_list *cmdlist, struct cmd_find_state *current,
|
|||||||
item->group = group;
|
item->group = group;
|
||||||
item->flags = flags;
|
item->flags = flags;
|
||||||
|
|
||||||
|
item->shared = shared;
|
||||||
item->cmdlist = cmdlist;
|
item->cmdlist = cmdlist;
|
||||||
item->cmd = cmd;
|
item->cmd = cmd;
|
||||||
|
|
||||||
if (current != NULL)
|
shared->references++;
|
||||||
cmd_find_copy_state(&item->current, current);
|
|
||||||
if (m != NULL)
|
|
||||||
memcpy(&item->mouse, m, sizeof item->mouse);
|
|
||||||
cmdlist->references++;
|
cmdlist->references++;
|
||||||
|
|
||||||
if (first == NULL)
|
if (first == NULL)
|
||||||
@@ -179,41 +189,63 @@ cmdq_get_command(struct cmd_list *cmdlist, struct cmd_find_state *current,
|
|||||||
return (first);
|
return (first);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fill in flag for a command. */
|
||||||
|
static enum cmd_retval
|
||||||
|
cmdq_find_flag(struct cmdq_item *item, struct cmd_find_state *fs,
|
||||||
|
const struct cmd_entry_flag *flag)
|
||||||
|
{
|
||||||
|
const char *value;
|
||||||
|
|
||||||
|
if (flag->flag == 0) {
|
||||||
|
cmd_find_clear_state(fs, 0);
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
value = args_get(item->cmd->args, flag->flag);
|
||||||
|
if (cmd_find_target(fs, item, value, flag->type, flag->flags) != 0) {
|
||||||
|
cmd_find_clear_state(fs, 0);
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
}
|
||||||
|
return (CMD_RETURN_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
/* Fire command on command queue. */
|
/* Fire command on command queue. */
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmdq_fire_command(struct cmdq_item *item)
|
cmdq_fire_command(struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct client *c = item->client;
|
struct client *c = item->client;
|
||||||
struct cmd *cmd = item->cmd;
|
struct cmd *cmd = item->cmd;
|
||||||
|
const struct cmd_entry *entry = cmd->entry;
|
||||||
enum cmd_retval retval;
|
enum cmd_retval retval;
|
||||||
const char *name;
|
|
||||||
struct cmd_find_state *fsp, fs;
|
struct cmd_find_state *fsp, fs;
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
flags = !!(cmd->flags & CMD_CONTROL);
|
flags = !!(cmd->flags & CMD_CONTROL);
|
||||||
cmdq_guard(item, "begin", flags);
|
cmdq_guard(item, "begin", flags);
|
||||||
|
|
||||||
if (cmd_prepare_state(cmd, item) != 0) {
|
|
||||||
retval = CMD_RETURN_ERROR;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if (item->client == NULL)
|
if (item->client == NULL)
|
||||||
item->client = cmd_find_client(item, NULL, CMD_FIND_QUIET);
|
item->client = cmd_find_client(item, NULL, 1);
|
||||||
|
retval = cmdq_find_flag(item, &item->source, &entry->source);
|
||||||
retval = cmd->entry->exec(cmd, item);
|
if (retval == CMD_RETURN_ERROR)
|
||||||
|
goto out;
|
||||||
|
retval = cmdq_find_flag(item, &item->target, &entry->target);
|
||||||
if (retval == CMD_RETURN_ERROR)
|
if (retval == CMD_RETURN_ERROR)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (cmd->entry->flags & CMD_AFTERHOOK) {
|
retval = entry->exec(cmd, item);
|
||||||
name = cmd->entry->name;
|
if (retval == CMD_RETURN_ERROR)
|
||||||
if (cmd_find_valid_state(&item->state.tflag))
|
goto out;
|
||||||
fsp = &item->state.tflag;
|
|
||||||
else {
|
if (entry->flags & CMD_AFTERHOOK) {
|
||||||
if (cmd_find_current(&fs, item, CMD_FIND_QUIET) != 0)
|
if (cmd_find_valid_state(&item->target))
|
||||||
goto out;
|
fsp = &item->target;
|
||||||
|
else if (cmd_find_valid_state(&item->shared->current))
|
||||||
|
fsp = &item->shared->current;
|
||||||
|
else if (cmd_find_from_client(&fs, item->client) == 0)
|
||||||
fsp = &fs;
|
fsp = &fs;
|
||||||
}
|
else
|
||||||
hooks_insert(fsp->s->hooks, item, fsp, "after-%s", name);
|
goto out;
|
||||||
|
hooks_insert(fsp->s->hooks, item, fsp, "after-%s", entry->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@@ -258,19 +290,17 @@ cmdq_fire_callback(struct cmdq_item *item)
|
|||||||
void
|
void
|
||||||
cmdq_format(struct cmdq_item *item, const char *key, const char *fmt, ...)
|
cmdq_format(struct cmdq_item *item, const char *key, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
struct cmdq_shared *shared = item->shared;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
struct cmdq_item *loop;
|
|
||||||
char *value;
|
char *value;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
xvasprintf(&value, fmt, ap);
|
xvasprintf(&value, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
for (loop = item; loop != NULL; loop = item->next) {
|
if (shared->formats == NULL)
|
||||||
if (loop->formats == NULL)
|
shared->formats = format_create(NULL, NULL, FORMAT_NONE, 0);
|
||||||
loop->formats = format_create(NULL, FORMAT_NONE, 0);
|
format_add(shared->formats, key, "%s", value);
|
||||||
format_add(loop->formats, key, "%s", value);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(value);
|
free(value);
|
||||||
}
|
}
|
||||||
@@ -319,8 +349,7 @@ cmdq_next(struct client *c)
|
|||||||
item->time = time(NULL);
|
item->time = time(NULL);
|
||||||
item->number = ++number;
|
item->number = ++number;
|
||||||
|
|
||||||
switch (item->type)
|
switch (item->type) {
|
||||||
{
|
|
||||||
case CMDQ_COMMAND:
|
case CMDQ_COMMAND:
|
||||||
retval = cmdq_fire_command(item);
|
retval = cmdq_fire_command(item);
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,6 @@ const struct cmd_entry cmd_refresh_client_entry = {
|
|||||||
.args = { "C:St:", 0, 0 },
|
.args = { "C:St:", 0, 0 },
|
||||||
.usage = "[-S] [-C size] " CMD_TARGET_CLIENT_USAGE,
|
.usage = "[-S] [-C size] " CMD_TARGET_CLIENT_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_CLIENT,
|
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_refresh_client_exec
|
.exec = cmd_refresh_client_exec
|
||||||
};
|
};
|
||||||
@@ -44,10 +42,13 @@ static enum cmd_retval
|
|||||||
cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct client *c = item->state.c;
|
struct client *c;
|
||||||
const char *size;
|
const char *size;
|
||||||
u_int w, h;
|
u_int w, h;
|
||||||
|
|
||||||
|
if ((c = cmd_find_client(item, args_get(args, 't'), 0)) == NULL)
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
|
||||||
if (args_has(args, 'C')) {
|
if (args_has(args, 'C')) {
|
||||||
if ((size = args_get(args, 'C')) == NULL) {
|
if ((size = args_get(args, 'C')) == NULL) {
|
||||||
cmdq_error(item, "missing size");
|
cmdq_error(item, "missing size");
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ const struct cmd_entry cmd_rename_session_entry = {
|
|||||||
.args = { "t:", 1, 1 },
|
.args = { "t:", 1, 1 },
|
||||||
.usage = CMD_TARGET_SESSION_USAGE " new-name",
|
.usage = CMD_TARGET_SESSION_USAGE " new-name",
|
||||||
|
|
||||||
.tflag = CMD_SESSION,
|
.target = { 't', CMD_FIND_SESSION, 0 },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_rename_session_exec
|
.exec = cmd_rename_session_exec
|
||||||
@@ -47,7 +47,7 @@ static enum cmd_retval
|
|||||||
cmd_rename_session_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_rename_session_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct session *s = item->state.tflag.s;
|
struct session *s = item->target.s;
|
||||||
const char *newname;
|
const char *newname;
|
||||||
|
|
||||||
newname = args->argv[0];
|
newname = args->argv[0];
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const struct cmd_entry cmd_rename_window_entry = {
|
|||||||
.args = { "t:", 1, 1 },
|
.args = { "t:", 1, 1 },
|
||||||
.usage = CMD_TARGET_WINDOW_USAGE " new-name",
|
.usage = CMD_TARGET_WINDOW_USAGE " new-name",
|
||||||
|
|
||||||
.tflag = CMD_WINDOW,
|
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_rename_window_exec
|
.exec = cmd_rename_window_exec
|
||||||
@@ -46,7 +46,7 @@ static enum cmd_retval
|
|||||||
cmd_rename_window_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_rename_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct winlink *wl = item->state.tflag.wl;
|
struct winlink *wl = item->target.wl;
|
||||||
|
|
||||||
window_set_name(wl->window, args->argv[0]);
|
window_set_name(wl->window, args->argv[0]);
|
||||||
options_set_number(wl->window->options, "automatic-rename", 0);
|
options_set_number(wl->window->options, "automatic-rename", 0);
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ const struct cmd_entry cmd_resize_pane_entry = {
|
|||||||
.usage = "[-DLMRUZ] [-x width] [-y height] " CMD_TARGET_PANE_USAGE " "
|
.usage = "[-DLMRUZ] [-x width] [-y height] " CMD_TARGET_PANE_USAGE " "
|
||||||
"[adjustment]",
|
"[adjustment]",
|
||||||
|
|
||||||
.tflag = CMD_PANE,
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_resize_pane_exec
|
.exec = cmd_resize_pane_exec
|
||||||
@@ -49,23 +49,24 @@ static enum cmd_retval
|
|||||||
cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct window_pane *wp = item->state.tflag.wp;
|
struct cmdq_shared *shared = item->shared;
|
||||||
struct winlink *wl = item->state.tflag.wl;
|
struct window_pane *wp = item->target.wp;
|
||||||
|
struct winlink *wl = item->target.wl;
|
||||||
struct window *w = wl->window;
|
struct window *w = wl->window;
|
||||||
struct client *c = item->client;
|
struct client *c = item->client;
|
||||||
struct session *s = item->state.tflag.s;
|
struct session *s = item->target.s;
|
||||||
const char *errstr;
|
const char *errstr;
|
||||||
char *cause;
|
char *cause;
|
||||||
u_int adjust;
|
u_int adjust;
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
if (args_has(args, 'M')) {
|
if (args_has(args, 'M')) {
|
||||||
if (cmd_mouse_window(&item->mouse, &s) == NULL)
|
if (cmd_mouse_window(&shared->mouse, &s) == NULL)
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
if (c == NULL || c->session != s)
|
if (c == NULL || c->session != s)
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update;
|
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update;
|
||||||
cmd_resize_pane_mouse_update(c, &item->mouse);
|
cmd_resize_pane_mouse_update(c, &shared->mouse);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ const struct cmd_entry cmd_respawn_pane_entry = {
|
|||||||
.args = { "kt:", 0, -1 },
|
.args = { "kt:", 0, -1 },
|
||||||
.usage = "[-k] " CMD_TARGET_PANE_USAGE " [command]",
|
.usage = "[-k] " CMD_TARGET_PANE_USAGE " [command]",
|
||||||
|
|
||||||
.tflag = CMD_PANE,
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_respawn_pane_exec
|
.exec = cmd_respawn_pane_exec
|
||||||
@@ -47,10 +47,10 @@ static enum cmd_retval
|
|||||||
cmd_respawn_pane_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_respawn_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct winlink *wl = item->state.tflag.wl;
|
struct winlink *wl = item->target.wl;
|
||||||
struct window *w = wl->window;
|
struct window *w = wl->window;
|
||||||
struct window_pane *wp = item->state.tflag.wp;
|
struct window_pane *wp = item->target.wp;
|
||||||
struct session *s = item->state.tflag.s;
|
struct session *s = item->target.s;
|
||||||
struct environ *env;
|
struct environ *env;
|
||||||
const char *path;
|
const char *path;
|
||||||
char *cause;
|
char *cause;
|
||||||
@@ -77,7 +77,7 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (envent != NULL)
|
if (envent != NULL)
|
||||||
path = envent->value;
|
path = envent->value;
|
||||||
|
|
||||||
env = environ_for_session(s);
|
env = environ_for_session(s, 0);
|
||||||
if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, NULL, env,
|
if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, NULL, env,
|
||||||
s->tio, &cause) != 0) {
|
s->tio, &cause) != 0) {
|
||||||
cmdq_error(item, "respawn pane failed: %s", cause);
|
cmdq_error(item, "respawn pane failed: %s", cause);
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ const struct cmd_entry cmd_respawn_window_entry = {
|
|||||||
.args = { "kt:", 0, -1 },
|
.args = { "kt:", 0, -1 },
|
||||||
.usage = "[-k] " CMD_TARGET_WINDOW_USAGE " [command]",
|
.usage = "[-k] " CMD_TARGET_WINDOW_USAGE " [command]",
|
||||||
|
|
||||||
.tflag = CMD_WINDOW,
|
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_respawn_window_exec
|
.exec = cmd_respawn_window_exec
|
||||||
@@ -47,8 +47,8 @@ static enum cmd_retval
|
|||||||
cmd_respawn_window_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_respawn_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct session *s = item->state.tflag.s;
|
struct session *s = item->target.s;
|
||||||
struct winlink *wl = item->state.tflag.wl;
|
struct winlink *wl = item->target.wl;
|
||||||
struct window *w = wl->window;
|
struct window *w = wl->window;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
struct environ *env;
|
struct environ *env;
|
||||||
@@ -81,7 +81,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (envent != NULL)
|
if (envent != NULL)
|
||||||
path = envent->value;
|
path = envent->value;
|
||||||
|
|
||||||
env = environ_for_session(s);
|
env = environ_for_session(s, 0);
|
||||||
if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, NULL, env,
|
if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, NULL, env,
|
||||||
s->tio, &cause) != 0) {
|
s->tio, &cause) != 0) {
|
||||||
cmdq_error(item, "respawn window failed: %s", cause);
|
cmdq_error(item, "respawn window failed: %s", cause);
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ const struct cmd_entry cmd_rotate_window_entry = {
|
|||||||
.args = { "Dt:U", 0, 0 },
|
.args = { "Dt:U", 0, 0 },
|
||||||
.usage = "[-DU] " CMD_TARGET_WINDOW_USAGE,
|
.usage = "[-DU] " CMD_TARGET_WINDOW_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_WINDOW,
|
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_rotate_window_exec
|
.exec = cmd_rotate_window_exec
|
||||||
@@ -43,7 +43,8 @@ const struct cmd_entry cmd_rotate_window_entry = {
|
|||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_rotate_window_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_rotate_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct winlink *wl = item->state.tflag.wl;
|
struct cmd_find_state *current = &item->shared->current;
|
||||||
|
struct winlink *wl = item->target.wl;
|
||||||
struct window *w = wl->window;
|
struct window *w = wl->window;
|
||||||
struct window_pane *wp, *wp2;
|
struct window_pane *wp, *wp2;
|
||||||
struct layout_cell *lc;
|
struct layout_cell *lc;
|
||||||
@@ -77,6 +78,7 @@ cmd_rotate_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if ((wp = TAILQ_PREV(w->active, window_panes, entry)) == NULL)
|
if ((wp = TAILQ_PREV(w->active, window_panes, entry)) == NULL)
|
||||||
wp = TAILQ_LAST(&w->panes, window_panes);
|
wp = TAILQ_LAST(&w->panes, window_panes);
|
||||||
window_set_active_pane(w, wp);
|
window_set_active_pane(w, wp);
|
||||||
|
cmd_find_from_winlink_pane(current, wl, wp);
|
||||||
server_redraw_window(w);
|
server_redraw_window(w);
|
||||||
} else {
|
} else {
|
||||||
wp = TAILQ_FIRST(&w->panes);
|
wp = TAILQ_FIRST(&w->panes);
|
||||||
@@ -104,6 +106,7 @@ cmd_rotate_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if ((wp = TAILQ_NEXT(w->active, entry)) == NULL)
|
if ((wp = TAILQ_NEXT(w->active, entry)) == NULL)
|
||||||
wp = TAILQ_FIRST(&w->panes);
|
wp = TAILQ_FIRST(&w->panes);
|
||||||
window_set_active_pane(w, wp);
|
window_set_active_pane(w, wp);
|
||||||
|
cmd_find_from_winlink_pane(current, wl, wp);
|
||||||
server_redraw_window(w);
|
server_redraw_window(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ const struct cmd_entry cmd_run_shell_entry = {
|
|||||||
.args = { "bt:", 1, 1 },
|
.args = { "bt:", 1, 1 },
|
||||||
.usage = "[-b] " CMD_TARGET_PANE_USAGE " shell-command",
|
.usage = "[-b] " CMD_TARGET_PANE_USAGE " shell-command",
|
||||||
|
|
||||||
.tflag = CMD_PANE_CANFAIL,
|
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_run_shell_exec
|
.exec = cmd_run_shell_exec
|
||||||
@@ -68,7 +68,7 @@ cmd_run_shell_print(struct job *job, const char *msg)
|
|||||||
cmdq_print(cdata->item, "%s", msg);
|
cmdq_print(cdata->item, "%s", msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (cmd_find_current (&fs, NULL, CMD_FIND_QUIET) != 0)
|
if (cmd_find_from_nothing(&fs) != 0)
|
||||||
return;
|
return;
|
||||||
wp = fs.wp;
|
wp = fs.wp;
|
||||||
if (wp == NULL)
|
if (wp == NULL)
|
||||||
@@ -86,10 +86,10 @@ cmd_run_shell_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct cmd_run_shell_data *cdata;
|
struct cmd_run_shell_data *cdata;
|
||||||
struct client *c = item->state.c;
|
struct client *c = cmd_find_client(item, NULL, 1);
|
||||||
struct session *s = item->state.tflag.s;
|
struct session *s = item->target.s;
|
||||||
struct winlink *wl = item->state.tflag.wl;
|
struct winlink *wl = item->target.wl;
|
||||||
struct window_pane *wp = item->state.tflag.wp;
|
struct window_pane *wp = item->target.wp;
|
||||||
const char *cwd;
|
const char *cwd;
|
||||||
|
|
||||||
if (item->client != NULL && item->client->session == NULL)
|
if (item->client != NULL && item->client->session == NULL)
|
||||||
@@ -110,8 +110,8 @@ cmd_run_shell_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (!args_has(args, 'b'))
|
if (!args_has(args, 'b'))
|
||||||
cdata->item = item;
|
cdata->item = item;
|
||||||
|
|
||||||
job_run(cdata->cmd, s, cwd, cmd_run_shell_callback, cmd_run_shell_free,
|
job_run(cdata->cmd, s, cwd, NULL, cmd_run_shell_callback,
|
||||||
cdata);
|
cmd_run_shell_free, cdata);
|
||||||
|
|
||||||
if (args_has(args, 'b'))
|
if (args_has(args, 'b'))
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ cmd_save_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (fwrite(bufdata, 1, bufsize, f) != bufsize) {
|
if (fwrite(bufdata, 1, bufsize, f) != bufsize) {
|
||||||
cmdq_error(item, "%s: write error", file);
|
cmdq_error(item, "%s: write error", file);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
free(file);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const struct cmd_entry cmd_select_layout_entry = {
|
|||||||
.args = { "nopt:", 0, 1 },
|
.args = { "nopt:", 0, 1 },
|
||||||
.usage = "[-nop] " CMD_TARGET_WINDOW_USAGE " [layout-name]",
|
.usage = "[-nop] " CMD_TARGET_WINDOW_USAGE " [layout-name]",
|
||||||
|
|
||||||
.tflag = CMD_WINDOW,
|
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_select_layout_exec
|
.exec = cmd_select_layout_exec
|
||||||
@@ -49,7 +49,7 @@ const struct cmd_entry cmd_next_layout_entry = {
|
|||||||
.args = { "t:", 0, 0 },
|
.args = { "t:", 0, 0 },
|
||||||
.usage = CMD_TARGET_WINDOW_USAGE,
|
.usage = CMD_TARGET_WINDOW_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_WINDOW,
|
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_select_layout_exec
|
.exec = cmd_select_layout_exec
|
||||||
@@ -62,7 +62,7 @@ const struct cmd_entry cmd_previous_layout_entry = {
|
|||||||
.args = { "t:", 0, 0 },
|
.args = { "t:", 0, 0 },
|
||||||
.usage = CMD_TARGET_WINDOW_USAGE,
|
.usage = CMD_TARGET_WINDOW_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_WINDOW,
|
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_select_layout_exec
|
.exec = cmd_select_layout_exec
|
||||||
@@ -72,7 +72,7 @@ static enum cmd_retval
|
|||||||
cmd_select_layout_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_select_layout_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct winlink *wl = item->state.tflag.wl;
|
struct winlink *wl = item->target.wl;
|
||||||
struct window *w;
|
struct window *w;
|
||||||
const char *layoutname;
|
const char *layoutname;
|
||||||
char *oldlayout;
|
char *oldlayout;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ const struct cmd_entry cmd_select_pane_entry = {
|
|||||||
.args = { "DdegLlMmP:Rt:U", 0, 0 },
|
.args = { "DdegLlMmP:Rt:U", 0, 0 },
|
||||||
.usage = "[-DdegLlMmRU] [-P style] " CMD_TARGET_PANE_USAGE,
|
.usage = "[-DdegLlMmRU] [-P style] " CMD_TARGET_PANE_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_PANE,
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_select_pane_exec
|
.exec = cmd_select_pane_exec
|
||||||
@@ -46,7 +46,7 @@ const struct cmd_entry cmd_last_pane_entry = {
|
|||||||
.args = { "det:", 0, 0 },
|
.args = { "det:", 0, 0 },
|
||||||
.usage = "[-de] " CMD_TARGET_WINDOW_USAGE,
|
.usage = "[-de] " CMD_TARGET_WINDOW_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_WINDOW,
|
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_select_pane_exec
|
.exec = cmd_select_pane_exec
|
||||||
@@ -56,31 +56,32 @@ static enum cmd_retval
|
|||||||
cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct winlink *wl = item->state.tflag.wl;
|
struct cmd_find_state *current = &item->shared->current;
|
||||||
|
struct winlink *wl = item->target.wl;
|
||||||
struct window *w = wl->window;
|
struct window *w = wl->window;
|
||||||
struct session *s = item->state.tflag.s;
|
struct session *s = item->target.s;
|
||||||
struct window_pane *wp = item->state.tflag.wp, *lastwp, *markedwp;
|
struct window_pane *wp = item->target.wp, *lastwp, *markedwp;
|
||||||
const char *style;
|
const char *style;
|
||||||
|
|
||||||
if (self->entry == &cmd_last_pane_entry || args_has(args, 'l')) {
|
if (self->entry == &cmd_last_pane_entry || args_has(args, 'l')) {
|
||||||
if (wl->window->last == NULL) {
|
lastwp = w->last;
|
||||||
|
if (lastwp == NULL) {
|
||||||
cmdq_error(item, "no last pane");
|
cmdq_error(item, "no last pane");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args_has(self->args, 'e'))
|
if (args_has(self->args, 'e'))
|
||||||
w->last->flags &= ~PANE_INPUTOFF;
|
lastwp->flags &= ~PANE_INPUTOFF;
|
||||||
else if (args_has(self->args, 'd'))
|
else if (args_has(self->args, 'd'))
|
||||||
w->last->flags |= PANE_INPUTOFF;
|
lastwp->flags |= PANE_INPUTOFF;
|
||||||
else {
|
else {
|
||||||
server_unzoom_window(w);
|
server_unzoom_window(w);
|
||||||
window_redraw_active_switch(w, w->last);
|
window_redraw_active_switch(w, lastwp);
|
||||||
if (window_set_active_pane(w, w->last)) {
|
if (window_set_active_pane(w, lastwp)) {
|
||||||
|
cmd_find_from_winlink(current, wl);
|
||||||
server_status_window(w);
|
server_status_window(w);
|
||||||
server_redraw_window_borders(w);
|
server_redraw_window_borders(w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,6 +156,7 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
}
|
}
|
||||||
window_redraw_active_switch(w, wp);
|
window_redraw_active_switch(w, wp);
|
||||||
if (window_set_active_pane(w, wp)) {
|
if (window_set_active_pane(w, wp)) {
|
||||||
|
cmd_find_from_winlink(current, wl);
|
||||||
server_status_window(w);
|
server_status_window(w);
|
||||||
server_redraw_window_borders(w);
|
server_redraw_window_borders(w);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const struct cmd_entry cmd_select_window_entry = {
|
|||||||
.args = { "lnpTt:", 0, 0 },
|
.args = { "lnpTt:", 0, 0 },
|
||||||
.usage = "[-lnpT] " CMD_TARGET_WINDOW_USAGE,
|
.usage = "[-lnpT] " CMD_TARGET_WINDOW_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_WINDOW,
|
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_select_window_exec
|
.exec = cmd_select_window_exec
|
||||||
@@ -49,7 +49,7 @@ const struct cmd_entry cmd_next_window_entry = {
|
|||||||
.args = { "at:", 0, 0 },
|
.args = { "at:", 0, 0 },
|
||||||
.usage = "[-a] " CMD_TARGET_SESSION_USAGE,
|
.usage = "[-a] " CMD_TARGET_SESSION_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_SESSION,
|
.target = { 't', CMD_FIND_SESSION, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_select_window_exec
|
.exec = cmd_select_window_exec
|
||||||
@@ -62,7 +62,7 @@ const struct cmd_entry cmd_previous_window_entry = {
|
|||||||
.args = { "at:", 0, 0 },
|
.args = { "at:", 0, 0 },
|
||||||
.usage = "[-a] " CMD_TARGET_SESSION_USAGE,
|
.usage = "[-a] " CMD_TARGET_SESSION_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_SESSION,
|
.target = { 't', CMD_FIND_SESSION, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_select_window_exec
|
.exec = cmd_select_window_exec
|
||||||
@@ -75,7 +75,7 @@ const struct cmd_entry cmd_last_window_entry = {
|
|||||||
.args = { "t:", 0, 0 },
|
.args = { "t:", 0, 0 },
|
||||||
.usage = CMD_TARGET_SESSION_USAGE,
|
.usage = CMD_TARGET_SESSION_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_SESSION,
|
.target = { 't', CMD_FIND_SESSION, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_select_window_exec
|
.exec = cmd_select_window_exec
|
||||||
@@ -84,9 +84,10 @@ const struct cmd_entry cmd_last_window_entry = {
|
|||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_select_window_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_select_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct winlink *wl = item->state.tflag.wl;
|
struct cmd_find_state *current = &item->shared->current;
|
||||||
struct session *s = item->state.tflag.s;
|
struct winlink *wl = item->target.wl;
|
||||||
int next, previous, last, activity;
|
struct session *s = item->target.s;
|
||||||
|
int next, previous, last, activity;
|
||||||
|
|
||||||
next = self->entry == &cmd_next_window_entry;
|
next = self->entry == &cmd_next_window_entry;
|
||||||
if (args_has(self->args, 'n'))
|
if (args_has(self->args, 'n'))
|
||||||
@@ -116,7 +117,7 @@ cmd_select_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
cmd_find_from_session(&item->shared->current, s);
|
||||||
server_redraw_session(s);
|
server_redraw_session(s);
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
@@ -128,9 +129,13 @@ cmd_select_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
cmdq_error(item, "no last window");
|
cmdq_error(item, "no last window");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
if (current->s == s)
|
||||||
|
cmd_find_from_session(current, s);
|
||||||
server_redraw_session(s);
|
server_redraw_session(s);
|
||||||
} else if (session_select(s, wl->idx) == 0)
|
} else if (session_select(s, wl->idx) == 0) {
|
||||||
|
cmd_find_from_session(current, s);
|
||||||
server_redraw_session(s);
|
server_redraw_session(s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
recalculate_sizes();
|
recalculate_sizes();
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const struct cmd_entry cmd_send_keys_entry = {
|
|||||||
.args = { "lXRMN:t:", 0, -1 },
|
.args = { "lXRMN:t:", 0, -1 },
|
||||||
.usage = "[-lXRM] [-N repeat-count] " CMD_TARGET_PANE_USAGE " key ...",
|
.usage = "[-lXRM] [-N repeat-count] " CMD_TARGET_PANE_USAGE " key ...",
|
||||||
|
|
||||||
.tflag = CMD_PANE,
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_send_keys_exec
|
.exec = cmd_send_keys_exec
|
||||||
@@ -49,20 +49,43 @@ const struct cmd_entry cmd_send_prefix_entry = {
|
|||||||
.args = { "2t:", 0, 0 },
|
.args = { "2t:", 0, 0 },
|
||||||
.usage = "[-2] " CMD_TARGET_PANE_USAGE,
|
.usage = "[-2] " CMD_TARGET_PANE_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_PANE,
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_send_keys_exec
|
.exec = cmd_send_keys_exec
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
cmd_send_keys_inject(struct client *c, struct cmdq_item *item, key_code key)
|
||||||
|
{
|
||||||
|
struct window_pane *wp = item->target.wp;
|
||||||
|
struct session *s = item->target.s;
|
||||||
|
struct key_table *table;
|
||||||
|
struct key_binding *bd, bd_find;
|
||||||
|
|
||||||
|
if (wp->mode == NULL || wp->mode->key_table == NULL) {
|
||||||
|
window_pane_key(wp, NULL, s, key, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
table = key_bindings_get_table(wp->mode->key_table(wp), 1);
|
||||||
|
|
||||||
|
bd_find.key = (key & ~KEYC_XTERM);
|
||||||
|
bd = RB_FIND(key_bindings, &table->key_bindings, &bd_find);
|
||||||
|
if (bd != NULL) {
|
||||||
|
table->references++;
|
||||||
|
key_bindings_dispatch(bd, c, NULL, &item->target);
|
||||||
|
key_bindings_unref_table(table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct client *c = item->state.c;
|
struct client *c = cmd_find_client(item, NULL, 1);
|
||||||
struct window_pane *wp = item->state.tflag.wp;
|
struct window_pane *wp = item->target.wp;
|
||||||
struct session *s = item->state.tflag.s;
|
struct session *s = item->target.s;
|
||||||
struct mouse_event *m = &item->mouse;
|
struct mouse_event *m = &item->shared->mouse;
|
||||||
struct utf8_data *ud, *uc;
|
struct utf8_data *ud, *uc;
|
||||||
wchar_t wc;
|
wchar_t wc;
|
||||||
int i, literal;
|
int i, literal;
|
||||||
@@ -108,7 +131,7 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
key = options_get_number(s->options, "prefix2");
|
key = options_get_number(s->options, "prefix2");
|
||||||
else
|
else
|
||||||
key = options_get_number(s->options, "prefix");
|
key = options_get_number(s->options, "prefix");
|
||||||
window_pane_key(wp, NULL, s, key, NULL);
|
cmd_send_keys_inject(c, item, key);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +146,7 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (!literal) {
|
if (!literal) {
|
||||||
key = key_string_lookup_string(args->argv[i]);
|
key = key_string_lookup_string(args->argv[i]);
|
||||||
if (key != KEYC_NONE && key != KEYC_UNKNOWN)
|
if (key != KEYC_NONE && key != KEYC_UNKNOWN)
|
||||||
window_pane_key(wp, NULL, s, key, NULL);
|
cmd_send_keys_inject(c, item, key);
|
||||||
else
|
else
|
||||||
literal = 1;
|
literal = 1;
|
||||||
}
|
}
|
||||||
@@ -132,7 +155,7 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
for (uc = ud; uc->size != 0; uc++) {
|
for (uc = ud; uc->size != 0; uc++) {
|
||||||
if (utf8_combine(uc, &wc) != UTF8_DONE)
|
if (utf8_combine(uc, &wc) != UTF8_DONE)
|
||||||
continue;
|
continue;
|
||||||
window_pane_key(wp, NULL, s, wc, NULL);
|
cmd_send_keys_inject(c, item, wc);
|
||||||
}
|
}
|
||||||
free(ud);
|
free(ud);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ const struct cmd_entry cmd_set_environment_entry = {
|
|||||||
.args = { "grt:u", 1, 2 },
|
.args = { "grt:u", 1, 2 },
|
||||||
.usage = "[-gru] " CMD_TARGET_SESSION_USAGE " name [value]",
|
.usage = "[-gru] " CMD_TARGET_SESSION_USAGE " name [value]",
|
||||||
|
|
||||||
.tflag = CMD_SESSION_CANFAIL,
|
.target = { 't', CMD_FIND_SESSION, CMD_FIND_CANFAIL },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_set_environment_exec
|
.exec = cmd_set_environment_exec
|
||||||
@@ -68,7 +68,7 @@ cmd_set_environment_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (args_has(self->args, 'g'))
|
if (args_has(self->args, 'g'))
|
||||||
env = global_environ;
|
env = global_environ;
|
||||||
else {
|
else {
|
||||||
if (item->state.tflag.s == NULL) {
|
if (item->target.s == NULL) {
|
||||||
target = args_get(args, 't');
|
target = args_get(args, 't');
|
||||||
if (target != NULL)
|
if (target != NULL)
|
||||||
cmdq_error(item, "no such session: %s", target);
|
cmdq_error(item, "no such session: %s", target);
|
||||||
@@ -76,7 +76,7 @@ cmd_set_environment_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
cmdq_error(item, "no current session");
|
cmdq_error(item, "no current session");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
env = item->state.tflag.s->environ;
|
env = item->target.s->environ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args_has(self->args, 'u')) {
|
if (args_has(self->args, 'u')) {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const struct cmd_entry cmd_set_hook_entry = {
|
|||||||
.args = { "gt:u", 1, 2 },
|
.args = { "gt:u", 1, 2 },
|
||||||
.usage = "[-gu] " CMD_TARGET_SESSION_USAGE " hook-name [command]",
|
.usage = "[-gu] " CMD_TARGET_SESSION_USAGE " hook-name [command]",
|
||||||
|
|
||||||
.tflag = CMD_SESSION_CANFAIL,
|
.target = { 't', CMD_FIND_SESSION, CMD_FIND_CANFAIL },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_set_hook_exec
|
.exec = cmd_set_hook_exec
|
||||||
@@ -49,7 +49,7 @@ const struct cmd_entry cmd_show_hooks_entry = {
|
|||||||
.args = { "gt:", 0, 1 },
|
.args = { "gt:", 0, 1 },
|
||||||
.usage = "[-g] " CMD_TARGET_SESSION_USAGE,
|
.usage = "[-g] " CMD_TARGET_SESSION_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_SESSION,
|
.target = { 't', CMD_FIND_SESSION, 0 },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_set_hook_exec
|
.exec = cmd_set_hook_exec
|
||||||
@@ -68,7 +68,7 @@ cmd_set_hook_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (args_has(args, 'g'))
|
if (args_has(args, 'g'))
|
||||||
hooks = global_hooks;
|
hooks = global_hooks;
|
||||||
else {
|
else {
|
||||||
if (item->state.tflag.s == NULL) {
|
if (item->target.s == NULL) {
|
||||||
target = args_get(args, 't');
|
target = args_get(args, 't');
|
||||||
if (target != NULL)
|
if (target != NULL)
|
||||||
cmdq_error(item, "no such session: %s", target);
|
cmdq_error(item, "no such session: %s", target);
|
||||||
@@ -76,7 +76,7 @@ cmd_set_hook_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
cmdq_error(item, "no current session");
|
cmdq_error(item, "no current session");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
hooks = item->state.tflag.s->hooks;
|
hooks = item->target.s->hooks;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->entry == &cmd_show_hooks_entry) {
|
if (self->entry == &cmd_show_hooks_entry) {
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ const struct cmd_entry cmd_set_option_entry = {
|
|||||||
.args = { "agoqst:uw", 1, 2 },
|
.args = { "agoqst:uw", 1, 2 },
|
||||||
.usage = "[-agosquw] [-t target-window] option [value]",
|
.usage = "[-agosquw] [-t target-window] option [value]",
|
||||||
|
|
||||||
.tflag = CMD_WINDOW_CANFAIL,
|
.target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_set_option_exec
|
.exec = cmd_set_option_exec
|
||||||
@@ -58,7 +58,7 @@ const struct cmd_entry cmd_set_window_option_entry = {
|
|||||||
.args = { "agoqt:u", 1, 2 },
|
.args = { "agoqt:u", 1, 2 },
|
||||||
.usage = "[-agoqu] " CMD_TARGET_WINDOW_USAGE " option [value]",
|
.usage = "[-agoqu] " CMD_TARGET_WINDOW_USAGE " option [value]",
|
||||||
|
|
||||||
.tflag = CMD_WINDOW_CANFAIL,
|
.target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_set_option_exec
|
.exec = cmd_set_option_exec
|
||||||
@@ -69,7 +69,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
int append = args_has(args, 'a');
|
int append = args_has(args, 'a');
|
||||||
struct cmd_find_state *fs = &item->state.tflag;
|
struct cmd_find_state *fs = &item->target;
|
||||||
struct session *s = fs->s;
|
struct session *s = fs->s;
|
||||||
struct winlink *wl = fs->wl;
|
struct winlink *wl = fs->wl;
|
||||||
struct window *w;
|
struct window *w;
|
||||||
@@ -77,7 +77,8 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
enum options_table_scope scope;
|
enum options_table_scope scope;
|
||||||
struct options *oo;
|
struct options *oo;
|
||||||
struct options_entry *parent, *o;
|
struct options_entry *parent, *o;
|
||||||
const char *name, *value, *target;
|
char *name;
|
||||||
|
const char *value, *target;
|
||||||
int window, idx, already, error, ambiguous;
|
int window, idx, already, error, ambiguous;
|
||||||
char *cause;
|
char *cause;
|
||||||
|
|
||||||
@@ -121,7 +122,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
cmdq_error(item, "%s", cause);
|
cmdq_error(item, "%s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
return (CMD_RETURN_ERROR);
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Which table should this option go into? */
|
/* Which table should this option go into? */
|
||||||
@@ -136,7 +137,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
cmdq_error(item, "no such session: %s", target);
|
cmdq_error(item, "no such session: %s", target);
|
||||||
else
|
else
|
||||||
cmdq_error(item, "no current session");
|
cmdq_error(item, "no current session");
|
||||||
return (CMD_RETURN_ERROR);
|
goto fail;
|
||||||
} else
|
} else
|
||||||
oo = s->options;
|
oo = s->options;
|
||||||
} else if (scope == OPTIONS_TABLE_WINDOW) {
|
} else if (scope == OPTIONS_TABLE_WINDOW) {
|
||||||
@@ -148,7 +149,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
cmdq_error(item, "no such window: %s", target);
|
cmdq_error(item, "no such window: %s", target);
|
||||||
else
|
else
|
||||||
cmdq_error(item, "no current window");
|
cmdq_error(item, "no current window");
|
||||||
return (CMD_RETURN_ERROR);
|
goto fail;
|
||||||
} else
|
} else
|
||||||
oo = wl->window->options;
|
oo = wl->window->options;
|
||||||
}
|
}
|
||||||
@@ -159,7 +160,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (idx != -1) {
|
if (idx != -1) {
|
||||||
if (*name == '@' || options_array_size(parent, NULL) == -1) {
|
if (*name == '@' || options_array_size(parent, NULL) == -1) {
|
||||||
cmdq_error(item, "not an array: %s", args->argv[0]);
|
cmdq_error(item, "not an array: %s", args->argv[0]);
|
||||||
return (CMD_RETURN_ERROR);
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,14 +178,14 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (args_has(args, 'q'))
|
if (args_has(args, 'q'))
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
cmdq_error(item, "already set: %s", args->argv[0]);
|
cmdq_error(item, "already set: %s", args->argv[0]);
|
||||||
return (CMD_RETURN_ERROR);
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Change the option. */
|
/* Change the option. */
|
||||||
if (args_has(args, 'u')) {
|
if (args_has(args, 'u')) {
|
||||||
if (o == NULL)
|
if (o == NULL)
|
||||||
return (CMD_RETURN_NORMAL);
|
goto fail;
|
||||||
if (idx == -1) {
|
if (idx == -1) {
|
||||||
if (oo == global_options ||
|
if (oo == global_options ||
|
||||||
oo == global_s_options ||
|
oo == global_s_options ||
|
||||||
@@ -197,17 +198,17 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
} else if (*name == '@') {
|
} else if (*name == '@') {
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
cmdq_error(item, "empty value");
|
cmdq_error(item, "empty value");
|
||||||
return (CMD_RETURN_ERROR);
|
goto fail;
|
||||||
}
|
}
|
||||||
options_set_string(oo, name, append, "%s", value);
|
options_set_string(oo, name, append, "%s", value);
|
||||||
} else if (idx == -1 && options_array_size(parent, NULL) == -1) {
|
} else if (idx == -1 && options_array_size(parent, NULL) == -1) {
|
||||||
error = cmd_set_option_set(self, item, oo, parent, value);
|
error = cmd_set_option_set(self, item, oo, parent, value);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
return (CMD_RETURN_ERROR);
|
goto fail;
|
||||||
} else {
|
} else {
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
cmdq_error(item, "empty value");
|
cmdq_error(item, "empty value");
|
||||||
return (CMD_RETURN_ERROR);
|
goto fail;
|
||||||
}
|
}
|
||||||
if (o == NULL)
|
if (o == NULL)
|
||||||
o = options_empty(oo, options_table_entry(parent));
|
o = options_empty(oo, options_table_entry(parent));
|
||||||
@@ -217,7 +218,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
options_array_assign(o, value);
|
options_array_assign(o, value);
|
||||||
} else if (options_array_set(o, idx, value, append) != 0) {
|
} else if (options_array_set(o, idx, value, append) != 0) {
|
||||||
cmdq_error(item, "invalid index: %s", args->argv[0]);
|
cmdq_error(item, "invalid index: %s", args->argv[0]);
|
||||||
return (CMD_RETURN_ERROR);
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,7 +262,12 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
server_redraw_client(c);
|
server_redraw_client(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(name);
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
free(name);
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ const struct cmd_entry cmd_show_environment_entry = {
|
|||||||
.args = { "gst:", 0, 1 },
|
.args = { "gst:", 0, 1 },
|
||||||
.usage = "[-gs] " CMD_TARGET_SESSION_USAGE " [name]",
|
.usage = "[-gs] " CMD_TARGET_SESSION_USAGE " [name]",
|
||||||
|
|
||||||
.tflag = CMD_SESSION_CANFAIL,
|
.target = { 't', CMD_FIND_SESSION, CMD_FIND_CANFAIL },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_show_environment_exec
|
.exec = cmd_show_environment_exec
|
||||||
@@ -97,7 +97,7 @@ cmd_show_environment_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
const char *target;
|
const char *target;
|
||||||
|
|
||||||
if ((target = args_get(args, 't')) != NULL) {
|
if ((target = args_get(args, 't')) != NULL) {
|
||||||
if (item->state.tflag.s == NULL) {
|
if (item->target.s == NULL) {
|
||||||
cmdq_error(item, "no such session: %s", target);
|
cmdq_error(item, "no such session: %s", target);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
@@ -106,7 +106,7 @@ cmd_show_environment_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (args_has(self->args, 'g'))
|
if (args_has(self->args, 'g'))
|
||||||
env = global_environ;
|
env = global_environ;
|
||||||
else {
|
else {
|
||||||
if (item->state.tflag.s == NULL) {
|
if (item->target.s == NULL) {
|
||||||
target = args_get(args, 't');
|
target = args_get(args, 't');
|
||||||
if (target != NULL)
|
if (target != NULL)
|
||||||
cmdq_error(item, "no such session: %s", target);
|
cmdq_error(item, "no such session: %s", target);
|
||||||
@@ -114,7 +114,7 @@ cmd_show_environment_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
cmdq_error(item, "no current session");
|
cmdq_error(item, "no current session");
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
env = item->state.tflag.s->environ;
|
env = item->target.s->environ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args->argc != 0) {
|
if (args->argc != 0) {
|
||||||
|
|||||||
@@ -38,8 +38,6 @@ const struct cmd_entry cmd_show_messages_entry = {
|
|||||||
.args = { "JTt:", 0, 0 },
|
.args = { "JTt:", 0, 0 },
|
||||||
.usage = "[-JT] " CMD_TARGET_CLIENT_USAGE,
|
.usage = "[-JT] " CMD_TARGET_CLIENT_USAGE,
|
||||||
|
|
||||||
.tflag = CMD_CLIENT,
|
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_show_messages_exec
|
.exec = cmd_show_messages_exec
|
||||||
};
|
};
|
||||||
@@ -75,7 +73,7 @@ cmd_show_messages_jobs(struct cmdq_item *item, int blank)
|
|||||||
u_int n;
|
u_int n;
|
||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
LIST_FOREACH(job, &all_jobs, lentry) {
|
LIST_FOREACH(job, &all_jobs, entry) {
|
||||||
if (blank) {
|
if (blank) {
|
||||||
cmdq_print(item, "%s", "");
|
cmdq_print(item, "%s", "");
|
||||||
blank = 0;
|
blank = 0;
|
||||||
@@ -91,11 +89,14 @@ static enum cmd_retval
|
|||||||
cmd_show_messages_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_show_messages_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct client *c = item->state.c;
|
struct client *c;
|
||||||
struct message_entry *msg;
|
struct message_entry *msg;
|
||||||
char *tim;
|
char *tim;
|
||||||
int done, blank;
|
int done, blank;
|
||||||
|
|
||||||
|
if ((c = cmd_find_client(item, args_get(args, 't'), 0)) == NULL)
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
|
||||||
done = blank = 0;
|
done = blank = 0;
|
||||||
if (args_has(args, 'T')) {
|
if (args_has(args, 'T')) {
|
||||||
blank = cmd_show_messages_terminals(item, blank);
|
blank = cmd_show_messages_terminals(item, blank);
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ const struct cmd_entry cmd_show_options_entry = {
|
|||||||
.args = { "gqst:vw", 0, 1 },
|
.args = { "gqst:vw", 0, 1 },
|
||||||
.usage = "[-gqsvw] [-t target-session|target-window] [option]",
|
.usage = "[-gqsvw] [-t target-session|target-window] [option]",
|
||||||
|
|
||||||
.tflag = CMD_WINDOW_CANFAIL,
|
.target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_show_options_exec
|
.exec = cmd_show_options_exec
|
||||||
@@ -54,7 +54,7 @@ const struct cmd_entry cmd_show_window_options_entry = {
|
|||||||
.args = { "gvt:", 0, 1 },
|
.args = { "gvt:", 0, 1 },
|
||||||
.usage = "[-gv] " CMD_TARGET_WINDOW_USAGE " [option]",
|
.usage = "[-gv] " CMD_TARGET_WINDOW_USAGE " [option]",
|
||||||
|
|
||||||
.tflag = CMD_WINDOW_CANFAIL,
|
.target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL },
|
||||||
|
|
||||||
.flags = CMD_AFTERHOOK,
|
.flags = CMD_AFTERHOOK,
|
||||||
.exec = cmd_show_options_exec
|
.exec = cmd_show_options_exec
|
||||||
@@ -64,7 +64,7 @@ static enum cmd_retval
|
|||||||
cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct cmd_find_state *fs = &item->state.tflag;
|
struct cmd_find_state *fs = &item->target;
|
||||||
struct options *oo;
|
struct options *oo;
|
||||||
enum options_table_scope scope;
|
enum options_table_scope scope;
|
||||||
char *cause;
|
char *cause;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ const struct cmd_entry cmd_split_window_entry = {
|
|||||||
.usage = "[-bdfhvP] [-c start-directory] [-F format] "
|
.usage = "[-bdfhvP] [-c start-directory] [-F format] "
|
||||||
"[-p percentage|-l size] " CMD_TARGET_PANE_USAGE " [command]",
|
"[-p percentage|-l size] " CMD_TARGET_PANE_USAGE " [command]",
|
||||||
|
|
||||||
.tflag = CMD_PANE,
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_split_window_exec
|
.exec = cmd_split_window_exec
|
||||||
@@ -52,12 +52,13 @@ const struct cmd_entry cmd_split_window_entry = {
|
|||||||
static enum cmd_retval
|
static enum cmd_retval
|
||||||
cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
|
struct cmd_find_state *current = &item->shared->current;
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct client *c = item->state.c;
|
struct client *c = cmd_find_client(item, NULL, 1);
|
||||||
struct session *s = item->state.tflag.s;
|
struct session *s = item->target.s;
|
||||||
struct winlink *wl = item->state.tflag.wl;
|
struct winlink *wl = item->target.wl;
|
||||||
struct window *w = wl->window;
|
struct window *w = wl->window;
|
||||||
struct window_pane *wp = item->state.tflag.wp, *new_wp = NULL;
|
struct window_pane *wp = item->target.wp, *new_wp = NULL;
|
||||||
struct environ *env;
|
struct environ *env;
|
||||||
const char *cmd, *path, *shell, *template, *cwd, *to_free;
|
const char *cmd, *path, *shell, *template, *cwd, *to_free;
|
||||||
char **argv, *cause, *new_cause, *cp;
|
char **argv, *cause, *new_cause, *cp;
|
||||||
@@ -142,7 +143,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (envent != NULL)
|
if (envent != NULL)
|
||||||
path = envent->value;
|
path = envent->value;
|
||||||
|
|
||||||
env = environ_for_session(s);
|
env = environ_for_session(s, 0);
|
||||||
if (window_pane_spawn(new_wp, argc, argv, path, shell, cwd, env,
|
if (window_pane_spawn(new_wp, argc, argv, path, shell, cwd, env,
|
||||||
s->tio, &cause) != 0) {
|
s->tio, &cause) != 0) {
|
||||||
environ_free(env);
|
environ_free(env);
|
||||||
@@ -155,6 +156,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (!args_has(args, 'd')) {
|
if (!args_has(args, 'd')) {
|
||||||
window_set_active_pane(w, new_wp);
|
window_set_active_pane(w, new_wp);
|
||||||
session_select(s, wl->idx);
|
session_select(s, wl->idx);
|
||||||
|
cmd_find_from_session(current, s);
|
||||||
server_redraw_session(s);
|
server_redraw_session(s);
|
||||||
} else
|
} else
|
||||||
server_status_session(s);
|
server_status_session(s);
|
||||||
@@ -171,12 +173,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (to_free != NULL)
|
if (to_free != NULL)
|
||||||
free((void *)to_free);
|
free((void *)to_free);
|
||||||
|
|
||||||
cmd_find_clear_state(&fs, NULL, 0);
|
cmd_find_from_winlink_pane(&fs, wl, new_wp);
|
||||||
fs.s = s;
|
|
||||||
fs.wl = wl;
|
|
||||||
fs.w = w;
|
|
||||||
fs.wp = new_wp;
|
|
||||||
cmd_find_log_state(__func__, &fs);
|
|
||||||
hooks_insert(s->hooks, item, &fs, "after-split-window");
|
hooks_insert(s->hooks, item, &fs, "after-split-window");
|
||||||
|
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ const struct cmd_entry cmd_swap_pane_entry = {
|
|||||||
.args = { "dDs:t:U", 0, 0 },
|
.args = { "dDs:t:U", 0, 0 },
|
||||||
.usage = "[-dDU] " CMD_SRCDST_PANE_USAGE,
|
.usage = "[-dDU] " CMD_SRCDST_PANE_USAGE,
|
||||||
|
|
||||||
.sflag = CMD_PANE_MARKED,
|
.source = { 's', CMD_FIND_PANE, CMD_FIND_DEFAULT_MARKED },
|
||||||
.tflag = CMD_PANE,
|
.target = { 't', CMD_FIND_PANE, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_swap_pane_exec
|
.exec = cmd_swap_pane_exec
|
||||||
@@ -50,10 +50,10 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct layout_cell *src_lc, *dst_lc;
|
struct layout_cell *src_lc, *dst_lc;
|
||||||
u_int sx, sy, xoff, yoff;
|
u_int sx, sy, xoff, yoff;
|
||||||
|
|
||||||
dst_w = item->state.tflag.wl->window;
|
dst_w = item->target.wl->window;
|
||||||
dst_wp = item->state.tflag.wp;
|
dst_wp = item->target.wp;
|
||||||
src_w = item->state.sflag.wl->window;
|
src_w = item->source.wl->window;
|
||||||
src_wp = item->state.sflag.wp;
|
src_wp = item->source.wp;
|
||||||
server_unzoom_window(dst_w);
|
server_unzoom_window(dst_w);
|
||||||
|
|
||||||
if (args_has(self->args, 'D')) {
|
if (args_has(self->args, 'D')) {
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ const struct cmd_entry cmd_swap_window_entry = {
|
|||||||
.args = { "ds:t:", 0, 0 },
|
.args = { "ds:t:", 0, 0 },
|
||||||
.usage = "[-d] " CMD_SRCDST_WINDOW_USAGE,
|
.usage = "[-d] " CMD_SRCDST_WINDOW_USAGE,
|
||||||
|
|
||||||
.sflag = CMD_WINDOW_MARKED,
|
.source = { 's', CMD_FIND_WINDOW, CMD_FIND_DEFAULT_MARKED },
|
||||||
.tflag = CMD_WINDOW,
|
.target = { 't', CMD_FIND_WINDOW, 0 },
|
||||||
|
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.exec = cmd_swap_window_exec
|
.exec = cmd_swap_window_exec
|
||||||
@@ -50,12 +50,12 @@ cmd_swap_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
struct winlink *wl_src, *wl_dst;
|
struct winlink *wl_src, *wl_dst;
|
||||||
struct window *w_src, *w_dst;
|
struct window *w_src, *w_dst;
|
||||||
|
|
||||||
wl_src = item->state.sflag.wl;
|
wl_src = item->source.wl;
|
||||||
src = item->state.sflag.s;
|
src = item->source.s;
|
||||||
sg_src = session_group_contains(src);
|
sg_src = session_group_contains(src);
|
||||||
|
|
||||||
wl_dst = item->state.tflag.wl;
|
wl_dst = item->target.wl;
|
||||||
dst = item->state.tflag.s;
|
dst = item->target.s;
|
||||||
sg_dst = session_group_contains(dst);
|
sg_dst = session_group_contains(dst);
|
||||||
|
|
||||||
if (src != dst && sg_src != NULL && sg_dst != NULL &&
|
if (src != dst && sg_src != NULL && sg_dst != NULL &&
|
||||||
|
|||||||
@@ -38,8 +38,7 @@ const struct cmd_entry cmd_switch_client_entry = {
|
|||||||
.usage = "[-Elnpr] [-c target-client] [-t target-session] "
|
.usage = "[-Elnpr] [-c target-client] [-t target-session] "
|
||||||
"[-T key-table]",
|
"[-T key-table]",
|
||||||
|
|
||||||
.cflag = CMD_CLIENT,
|
/* -t is special */
|
||||||
.tflag = CMD_SESSION_WITHPANE,
|
|
||||||
|
|
||||||
.flags = CMD_READONLY,
|
.flags = CMD_READONLY,
|
||||||
.exec = cmd_switch_client_exec
|
.exec = cmd_switch_client_exec
|
||||||
@@ -49,13 +48,32 @@ static enum cmd_retval
|
|||||||
cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
|
cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
|
||||||
{
|
{
|
||||||
struct args *args = self->args;
|
struct args *args = self->args;
|
||||||
struct cmd_state *state = &item->state;
|
const char *tflag = args_get(args, 't');
|
||||||
struct client *c = state->c;
|
enum cmd_find_type type;
|
||||||
struct session *s = item->state.tflag.s;
|
int flags;
|
||||||
|
struct client *c;
|
||||||
|
struct session *s;
|
||||||
|
struct winlink *wl;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
const char *tablename;
|
const char *tablename;
|
||||||
struct key_table *table;
|
struct key_table *table;
|
||||||
|
|
||||||
|
if ((c = cmd_find_client(item, args_get(args, 'c'), 0)) == NULL)
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
|
||||||
|
if (tflag != NULL && tflag[strcspn(tflag, ":.")] != '\0') {
|
||||||
|
type = CMD_FIND_PANE;
|
||||||
|
flags = 0;
|
||||||
|
} else {
|
||||||
|
type = CMD_FIND_SESSION;
|
||||||
|
flags = CMD_FIND_PREFER_UNATTACHED;
|
||||||
|
}
|
||||||
|
if (cmd_find_target(&item->target, item, tflag, type, flags) != 0)
|
||||||
|
return (CMD_RETURN_ERROR);
|
||||||
|
s = item->target.s;
|
||||||
|
wl = item->target.wl;
|
||||||
|
wp = item->target.wp;
|
||||||
|
|
||||||
if (args_has(args, 'r'))
|
if (args_has(args, 'r'))
|
||||||
c->flags ^= CLIENT_READONLY;
|
c->flags ^= CLIENT_READONLY;
|
||||||
|
|
||||||
@@ -94,11 +112,11 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
} else {
|
} else {
|
||||||
if (item->client == NULL)
|
if (item->client == NULL)
|
||||||
return (CMD_RETURN_NORMAL);
|
return (CMD_RETURN_NORMAL);
|
||||||
if (state->tflag.wl != NULL) {
|
if (wl != NULL) {
|
||||||
wp = state->tflag.wp;
|
|
||||||
if (wp != NULL)
|
if (wp != NULL)
|
||||||
window_set_active_pane(wp->window, wp);
|
window_set_active_pane(wp->window, wp);
|
||||||
session_set_current(s, state->tflag.wl);
|
session_set_current(s, wl);
|
||||||
|
cmd_find_from_session(&item->shared->current, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,9 +126,10 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
if (c->session != NULL && c->session != s)
|
if (c->session != NULL && c->session != s)
|
||||||
c->last_session = c->session;
|
c->last_session = c->session;
|
||||||
c->session = s;
|
c->session = s;
|
||||||
if (!item->repeat)
|
if (~item->shared->flags & CMDQ_SHARED_REPEAT)
|
||||||
server_client_set_key_table(c, NULL);
|
server_client_set_key_table(c, NULL);
|
||||||
status_timer_start(c);
|
status_timer_start(c);
|
||||||
|
notify_client("client-session-changed", c);
|
||||||
session_update_activity(s, NULL);
|
session_update_activity(s, NULL);
|
||||||
gettimeofday(&s->last_attached_time, NULL);
|
gettimeofday(&s->last_attached_time, NULL);
|
||||||
|
|
||||||
|
|||||||
184
cmd.c
184
cmd.c
@@ -447,190 +447,6 @@ usage:
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
cmd_prepare_state_flag(char c, const char *target, enum cmd_entry_flag flag,
|
|
||||||
struct cmdq_item *item)
|
|
||||||
{
|
|
||||||
int targetflags, error;
|
|
||||||
struct cmd_find_state *fs = NULL;
|
|
||||||
struct cmd_find_state current;
|
|
||||||
|
|
||||||
if (flag == CMD_NONE ||
|
|
||||||
flag == CMD_CLIENT ||
|
|
||||||
flag == CMD_CLIENT_CANFAIL)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
if (c == 't')
|
|
||||||
fs = &item->state.tflag;
|
|
||||||
else if (c == 's')
|
|
||||||
fs = &item->state.sflag;
|
|
||||||
|
|
||||||
if (flag == CMD_SESSION_WITHPANE) {
|
|
||||||
if (target != NULL && target[strcspn(target, ":.")] != '\0')
|
|
||||||
flag = CMD_PANE;
|
|
||||||
else
|
|
||||||
flag = CMD_SESSION_PREFERUNATTACHED;
|
|
||||||
}
|
|
||||||
|
|
||||||
targetflags = 0;
|
|
||||||
switch (flag) {
|
|
||||||
case CMD_SESSION:
|
|
||||||
case CMD_SESSION_CANFAIL:
|
|
||||||
case CMD_SESSION_PREFERUNATTACHED:
|
|
||||||
case CMD_SESSION_WITHPANE:
|
|
||||||
if (flag == CMD_SESSION_CANFAIL)
|
|
||||||
targetflags |= CMD_FIND_QUIET;
|
|
||||||
if (flag == CMD_SESSION_PREFERUNATTACHED)
|
|
||||||
targetflags |= CMD_FIND_PREFER_UNATTACHED;
|
|
||||||
break;
|
|
||||||
case CMD_MOVEW_R:
|
|
||||||
flag = CMD_WINDOW_INDEX;
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case CMD_WINDOW:
|
|
||||||
case CMD_WINDOW_CANFAIL:
|
|
||||||
case CMD_WINDOW_MARKED:
|
|
||||||
case CMD_WINDOW_INDEX:
|
|
||||||
if (flag == CMD_WINDOW_CANFAIL)
|
|
||||||
targetflags |= CMD_FIND_QUIET;
|
|
||||||
if (flag == CMD_WINDOW_MARKED)
|
|
||||||
targetflags |= CMD_FIND_DEFAULT_MARKED;
|
|
||||||
if (flag == CMD_WINDOW_INDEX)
|
|
||||||
targetflags |= CMD_FIND_WINDOW_INDEX;
|
|
||||||
break;
|
|
||||||
case CMD_PANE:
|
|
||||||
case CMD_PANE_CANFAIL:
|
|
||||||
case CMD_PANE_MARKED:
|
|
||||||
if (flag == CMD_PANE_CANFAIL)
|
|
||||||
targetflags |= CMD_FIND_QUIET;
|
|
||||||
if (flag == CMD_PANE_MARKED)
|
|
||||||
targetflags |= CMD_FIND_DEFAULT_MARKED;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
fatalx("unknown %cflag %d", c, flag);
|
|
||||||
}
|
|
||||||
log_debug("%s: flag %c %d %#x", __func__, c, flag, targetflags);
|
|
||||||
|
|
||||||
error = cmd_find_current(¤t, item, targetflags);
|
|
||||||
if (error != 0) {
|
|
||||||
if (~targetflags & CMD_FIND_QUIET)
|
|
||||||
return (-1);
|
|
||||||
cmd_find_clear_state(¤t, NULL, 0);
|
|
||||||
}
|
|
||||||
if (!cmd_find_empty_state(¤t) && !cmd_find_valid_state(¤t))
|
|
||||||
fatalx("invalid current state");
|
|
||||||
|
|
||||||
switch (flag) {
|
|
||||||
case CMD_NONE:
|
|
||||||
case CMD_CLIENT:
|
|
||||||
case CMD_CLIENT_CANFAIL:
|
|
||||||
return (0);
|
|
||||||
case CMD_SESSION:
|
|
||||||
case CMD_SESSION_CANFAIL:
|
|
||||||
case CMD_SESSION_PREFERUNATTACHED:
|
|
||||||
case CMD_SESSION_WITHPANE:
|
|
||||||
error = cmd_find_target(fs, ¤t, item, target,
|
|
||||||
CMD_FIND_SESSION, targetflags);
|
|
||||||
if (error != 0)
|
|
||||||
goto error;
|
|
||||||
break;
|
|
||||||
case CMD_MOVEW_R:
|
|
||||||
error = cmd_find_target(fs, ¤t, item, target,
|
|
||||||
CMD_FIND_SESSION, CMD_FIND_QUIET);
|
|
||||||
if (error == 0)
|
|
||||||
break;
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
case CMD_WINDOW:
|
|
||||||
case CMD_WINDOW_CANFAIL:
|
|
||||||
case CMD_WINDOW_MARKED:
|
|
||||||
case CMD_WINDOW_INDEX:
|
|
||||||
error = cmd_find_target(fs, ¤t, item, target,
|
|
||||||
CMD_FIND_WINDOW, targetflags);
|
|
||||||
if (error != 0)
|
|
||||||
goto error;
|
|
||||||
break;
|
|
||||||
case CMD_PANE:
|
|
||||||
case CMD_PANE_CANFAIL:
|
|
||||||
case CMD_PANE_MARKED:
|
|
||||||
error = cmd_find_target(fs, ¤t, item, target,
|
|
||||||
CMD_FIND_PANE, targetflags);
|
|
||||||
if (error != 0)
|
|
||||||
goto error;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
fatalx("unknown %cflag %d", c, flag);
|
|
||||||
}
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
error:
|
|
||||||
if (~targetflags & CMD_FIND_QUIET)
|
|
||||||
return (-1);
|
|
||||||
cmd_find_clear_state(fs, NULL, 0);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
cmd_prepare_state(struct cmd *cmd, struct cmdq_item *item)
|
|
||||||
{
|
|
||||||
const struct cmd_entry *entry = cmd->entry;
|
|
||||||
struct cmd_state *state = &item->state;
|
|
||||||
char *tmp;
|
|
||||||
enum cmd_entry_flag flag;
|
|
||||||
const char *s;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
tmp = cmd_print(cmd);
|
|
||||||
log_debug("preparing state for %s (client %p)", tmp, item->client);
|
|
||||||
free(tmp);
|
|
||||||
|
|
||||||
state->c = NULL;
|
|
||||||
cmd_find_clear_state(&state->tflag, NULL, 0);
|
|
||||||
cmd_find_clear_state(&state->sflag, NULL, 0);
|
|
||||||
|
|
||||||
flag = cmd->entry->cflag;
|
|
||||||
if (flag == CMD_NONE) {
|
|
||||||
flag = cmd->entry->tflag;
|
|
||||||
if (flag == CMD_CLIENT || flag == CMD_CLIENT_CANFAIL)
|
|
||||||
s = args_get(cmd->args, 't');
|
|
||||||
else
|
|
||||||
s = NULL;
|
|
||||||
} else
|
|
||||||
s = args_get(cmd->args, 'c');
|
|
||||||
switch (flag) {
|
|
||||||
case CMD_CLIENT:
|
|
||||||
state->c = cmd_find_client(item, s, 0);
|
|
||||||
if (state->c == NULL)
|
|
||||||
return (-1);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
state->c = cmd_find_client(item, s, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
log_debug("using client %p", state->c);
|
|
||||||
|
|
||||||
s = args_get(cmd->args, 't');
|
|
||||||
log_debug("preparing -t state: target %s", s == NULL ? "none" : s);
|
|
||||||
|
|
||||||
error = cmd_prepare_state_flag('t', s, entry->tflag, item);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
s = args_get(cmd->args, 's');
|
|
||||||
log_debug("preparing -s state: target %s", s == NULL ? "none" : s);
|
|
||||||
|
|
||||||
error = cmd_prepare_state_flag('s', s, entry->sflag, item);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
if (!cmd_find_empty_state(&state->tflag) &&
|
|
||||||
!cmd_find_valid_state(&state->tflag))
|
|
||||||
fatalx("invalid -t state");
|
|
||||||
if (!cmd_find_empty_state(&state->sflag) &&
|
|
||||||
!cmd_find_valid_state(&state->sflag))
|
|
||||||
fatalx("invalid -s state");
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
cmd_print(struct cmd *cmd)
|
cmd_print(struct cmd *cmd)
|
||||||
{
|
{
|
||||||
|
|||||||
13
compat.h
13
compat.h
@@ -18,6 +18,7 @@
|
|||||||
#define COMPAT_H
|
#define COMPAT_H
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
@@ -283,9 +284,15 @@ int b64_ntop(const char *, size_t, char *, size_t);
|
|||||||
int b64_pton(const char *, u_char *, size_t);
|
int b64_pton(const char *, u_char *, size_t);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_FDFORKPTY
|
||||||
|
/* fdforkpty.c */
|
||||||
|
int getptmfd(void);
|
||||||
|
pid_t fdforkpty(int, int *, char *, struct termios *,
|
||||||
|
struct winsize *);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_FORKPTY
|
#ifndef HAVE_FORKPTY
|
||||||
/* forkpty.c */
|
/* forkpty.c */
|
||||||
#include <sys/ioctl.h>
|
|
||||||
pid_t forkpty(int *, char *, struct termios *, struct winsize *);
|
pid_t forkpty(int *, char *, struct termios *, struct winsize *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -337,9 +344,7 @@ int utf8proc_mbtowc(wchar_t *, const char *, size_t);
|
|||||||
int utf8proc_wctomb(char *, wchar_t);
|
int utf8proc_wctomb(char *, wchar_t);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_GETOPT
|
#ifndef HAVE_GETOPT
|
||||||
#include <getopt.h>
|
|
||||||
#else
|
|
||||||
/* getopt.c */
|
/* getopt.c */
|
||||||
extern int BSDopterr;
|
extern int BSDopterr;
|
||||||
extern int BSDoptind;
|
extern int BSDoptind;
|
||||||
|
|||||||
34
compat/fdforkpty.c
Normal file
34
compat/fdforkpty.c
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "compat.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
getptmfd(void)
|
||||||
|
{
|
||||||
|
return (INT_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t
|
||||||
|
fdforkpty(__unused int ptmfd, int *master, char *name, struct termios *tio,
|
||||||
|
struct winsize *ws)
|
||||||
|
{
|
||||||
|
return (forkpty(master, name, tio, ws));
|
||||||
|
}
|
||||||
@@ -29,7 +29,8 @@ void fatal(const char *, ...);
|
|||||||
void fatalx(const char *, ...);
|
void fatalx(const char *, ...);
|
||||||
|
|
||||||
pid_t
|
pid_t
|
||||||
forkpty(int *master, unused char *name, struct termios *tio, struct winsize *ws)
|
forkpty(int *master, __unused char *name, struct termios *tio,
|
||||||
|
struct winsize *ws)
|
||||||
{
|
{
|
||||||
int slave = -1, fd, pipe_fd[2];
|
int slave = -1, fd, pipe_fd[2];
|
||||||
char *path, dummy;
|
char *path, dummy;
|
||||||
|
|||||||
@@ -15,13 +15,15 @@
|
|||||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
|
||||||
int
|
int
|
||||||
setenv(const char *name, const char *value, unused int overwrite)
|
setenv(const char *name, const char *value, __unused int overwrite)
|
||||||
{
|
{
|
||||||
char *newval;
|
char *newval;
|
||||||
|
|
||||||
|
|||||||
11
configure.ac
11
configure.ac
@@ -1,6 +1,6 @@
|
|||||||
# configure.ac
|
# configure.ac
|
||||||
|
|
||||||
AC_INIT(tmux, 2.4)
|
AC_INIT(tmux, 2.5)
|
||||||
AC_PREREQ([2.60])
|
AC_PREREQ([2.60])
|
||||||
|
|
||||||
AC_CONFIG_AUX_DIR(etc)
|
AC_CONFIG_AUX_DIR(etc)
|
||||||
@@ -35,6 +35,7 @@ AC_USE_SYSTEM_EXTENSIONS
|
|||||||
test "$sysconfdir" = '${prefix}/etc' && sysconfdir=/etc
|
test "$sysconfdir" = '${prefix}/etc' && sysconfdir=/etc
|
||||||
|
|
||||||
# Is this --enable-debug?
|
# Is this --enable-debug?
|
||||||
|
test "x$VERSION" = xmaster && enable_debug=yes
|
||||||
AC_ARG_ENABLE(
|
AC_ARG_ENABLE(
|
||||||
debug,
|
debug,
|
||||||
AC_HELP_STRING(--enable-debug, enable debug build flags),
|
AC_HELP_STRING(--enable-debug, enable debug build flags),
|
||||||
@@ -453,7 +454,13 @@ else
|
|||||||
AC_LIBOBJ(getopt)
|
AC_LIBOBJ(getopt)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Look for forkpty in libutil. compat/forkpty-*.c is linked if not found.
|
# Look for fdforkpty and forkpty in libutil.
|
||||||
|
AC_SEARCH_LIBS(fdforkpty, util, found_fdforkpty=yes, found_fdforkpty=no)
|
||||||
|
if test "x$found_fdforkpty" = xyes; then
|
||||||
|
AC_DEFINE(HAVE_FDFORKPTY)
|
||||||
|
else
|
||||||
|
AC_LIBOBJ(fdforkpty)
|
||||||
|
fi
|
||||||
AC_SEARCH_LIBS(forkpty, util, found_forkpty=yes, found_forkpty=no)
|
AC_SEARCH_LIBS(forkpty, util, found_forkpty=yes, found_forkpty=no)
|
||||||
if test "x$found_forkpty" = xyes; then
|
if test "x$found_forkpty" = xyes; then
|
||||||
AC_DEFINE(HAVE_FORKPTY)
|
AC_DEFINE(HAVE_FORKPTY)
|
||||||
|
|||||||
@@ -59,14 +59,27 @@ control_notify_input(struct client *c, struct window_pane *wp,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
control_notify_pane_mode_changed(int pane)
|
||||||
|
{
|
||||||
|
struct client *c;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
|
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
control_write(c, "%%pane-mode-changed %%%u", pane);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
control_notify_window_layout_changed(struct window *w)
|
control_notify_window_layout_changed(struct window *w)
|
||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
const char *template;
|
const char *template;
|
||||||
char *cp;
|
char *cp;
|
||||||
|
|
||||||
template = "%layout-change #{window_id} #{window_layout} "
|
template = "%layout-change #{window_id} #{window_layout} "
|
||||||
"#{window_visible_layout} #{window_flags}";
|
"#{window_visible_layout} #{window_flags}";
|
||||||
@@ -96,6 +109,20 @@ control_notify_window_layout_changed(struct window *w)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
control_notify_window_pane_changed(struct window *w)
|
||||||
|
{
|
||||||
|
struct client *c;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
|
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
control_write(c, "%%window-pane-changed @%u %%%u", w->id,
|
||||||
|
w->active->id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
control_notify_window_unlinked(__unused struct session *s, struct window *w)
|
control_notify_window_unlinked(__unused struct session *s, struct window *w)
|
||||||
{
|
{
|
||||||
@@ -154,15 +181,27 @@ control_notify_window_renamed(struct window *w)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
control_notify_client_session_changed(struct client *c)
|
control_notify_client_session_changed(struct client *cc)
|
||||||
{
|
{
|
||||||
|
struct client *c;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
|
|
||||||
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
|
if (cc->session == NULL)
|
||||||
return;
|
return;
|
||||||
s = c->session;
|
s = cc->session;
|
||||||
|
|
||||||
control_write(c, "%%session-changed $%u %s", s->id, s->name);
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
|
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c) || c->session == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (cc == c) {
|
||||||
|
control_write(c, "%%session-changed $%u %s", s->id,
|
||||||
|
s->name);
|
||||||
|
} else {
|
||||||
|
control_write(c, "%%client-session-changed %s $%u %s",
|
||||||
|
cc->name, s->id, s->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -203,3 +242,17 @@ control_notify_session_closed(__unused struct session *s)
|
|||||||
control_write(c, "%%sessions-changed");
|
control_write(c, "%%sessions-changed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
control_notify_session_window_changed(struct session *s)
|
||||||
|
{
|
||||||
|
struct client *c;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
|
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
control_write(c, "%%session-window-changed $%u @%u", s->id,
|
||||||
|
s->curw->window->id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ environ_log(struct environ *env, const char *prefix)
|
|||||||
|
|
||||||
/* Create initial environment for new child. */
|
/* Create initial environment for new child. */
|
||||||
struct environ *
|
struct environ *
|
||||||
environ_for_session(struct session *s)
|
environ_for_session(struct session *s, int no_TERM)
|
||||||
{
|
{
|
||||||
struct environ *env;
|
struct environ *env;
|
||||||
const char *value;
|
const char *value;
|
||||||
@@ -233,8 +233,10 @@ environ_for_session(struct session *s)
|
|||||||
if (s != NULL)
|
if (s != NULL)
|
||||||
environ_copy(s->environ, env);
|
environ_copy(s->environ, env);
|
||||||
|
|
||||||
value = options_get_string(global_options, "default-terminal");
|
if (!no_TERM) {
|
||||||
environ_set(env, "TERM", "%s", value);
|
value = options_get_string(global_options, "default-terminal");
|
||||||
|
environ_set(env, "TERM", "%s", value);
|
||||||
|
}
|
||||||
|
|
||||||
if (s != NULL)
|
if (s != NULL)
|
||||||
idx = s->id;
|
idx = s->id;
|
||||||
|
|||||||
200
format.c
200
format.c
@@ -40,7 +40,6 @@
|
|||||||
struct format_entry;
|
struct format_entry;
|
||||||
typedef void (*format_cb)(struct format_tree *, struct format_entry *);
|
typedef void (*format_cb)(struct format_tree *, struct format_entry *);
|
||||||
|
|
||||||
static void format_job_callback(struct job *);
|
|
||||||
static char *format_job_get(struct format_tree *, const char *);
|
static char *format_job_get(struct format_tree *, const char *);
|
||||||
static void format_job_timer(int, short, void *);
|
static void format_job_timer(int, short, void *);
|
||||||
|
|
||||||
@@ -76,17 +75,19 @@ static int format_replace(struct format_tree *, const char *, size_t,
|
|||||||
static void format_defaults_session(struct format_tree *,
|
static void format_defaults_session(struct format_tree *,
|
||||||
struct session *);
|
struct session *);
|
||||||
static void format_defaults_client(struct format_tree *, struct client *);
|
static void format_defaults_client(struct format_tree *, struct client *);
|
||||||
static void format_defaults_winlink(struct format_tree *, struct session *,
|
static void format_defaults_winlink(struct format_tree *,
|
||||||
struct winlink *);
|
struct winlink *);
|
||||||
|
|
||||||
/* Entry in format job tree. */
|
/* Entry in format job tree. */
|
||||||
struct format_job {
|
struct format_job {
|
||||||
|
struct client *client;
|
||||||
u_int tag;
|
u_int tag;
|
||||||
const char *cmd;
|
const char *cmd;
|
||||||
const char *expanded;
|
const char *expanded;
|
||||||
|
|
||||||
time_t last;
|
time_t last;
|
||||||
char *out;
|
char *out;
|
||||||
|
int updated;
|
||||||
|
|
||||||
struct job *job;
|
struct job *job;
|
||||||
int status;
|
int status;
|
||||||
@@ -129,9 +130,11 @@ struct format_entry {
|
|||||||
/* Format entry tree. */
|
/* Format entry tree. */
|
||||||
struct format_tree {
|
struct format_tree {
|
||||||
struct window *w;
|
struct window *w;
|
||||||
|
struct winlink *wl;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
|
|
||||||
|
struct client *client;
|
||||||
u_int tag;
|
u_int tag;
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
@@ -207,17 +210,41 @@ static const char *format_lower[] = {
|
|||||||
NULL /* z */
|
NULL /* z */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Format job callback. */
|
/* Format job update callback. */
|
||||||
static void
|
static void
|
||||||
format_job_callback(struct job *job)
|
format_job_update(struct job *job)
|
||||||
|
{
|
||||||
|
struct format_job *fj = job->data;
|
||||||
|
char *line;
|
||||||
|
time_t t;
|
||||||
|
struct client *c;
|
||||||
|
|
||||||
|
if ((line = evbuffer_readline(job->event->input)) == NULL)
|
||||||
|
return;
|
||||||
|
fj->updated = 1;
|
||||||
|
|
||||||
|
free(fj->out);
|
||||||
|
fj->out = line;
|
||||||
|
|
||||||
|
log_debug("%s: %s: %s", __func__, fj->cmd, fj->out);
|
||||||
|
|
||||||
|
t = time (NULL);
|
||||||
|
if (fj->status && fj->last != t) {
|
||||||
|
TAILQ_FOREACH(c, &clients, entry)
|
||||||
|
server_status_client(c);
|
||||||
|
fj->last = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Format job complete callback. */
|
||||||
|
static void
|
||||||
|
format_job_complete(struct job *job)
|
||||||
{
|
{
|
||||||
struct format_job *fj = job->data;
|
struct format_job *fj = job->data;
|
||||||
char *line, *buf;
|
char *line, *buf;
|
||||||
size_t len;
|
size_t len;
|
||||||
struct client *c;
|
|
||||||
|
|
||||||
fj->job = NULL;
|
fj->job = NULL;
|
||||||
free(fj->out);
|
|
||||||
|
|
||||||
buf = NULL;
|
buf = NULL;
|
||||||
if ((line = evbuffer_readline(job->event->input)) == NULL) {
|
if ((line = evbuffer_readline(job->event->input)) == NULL) {
|
||||||
@@ -228,37 +255,52 @@ format_job_callback(struct job *job)
|
|||||||
buf[len] = '\0';
|
buf[len] = '\0';
|
||||||
} else
|
} else
|
||||||
buf = line;
|
buf = line;
|
||||||
fj->out = buf;
|
|
||||||
|
if (*buf != '\0' || !fj->updated) {
|
||||||
|
free(fj->out);
|
||||||
|
fj->out = buf;
|
||||||
|
log_debug("%s: %s: %s", __func__, fj->cmd, fj->out);
|
||||||
|
} else
|
||||||
|
free(buf);
|
||||||
|
|
||||||
if (fj->status) {
|
if (fj->status) {
|
||||||
TAILQ_FOREACH(c, &clients, entry)
|
if (fj->client != NULL)
|
||||||
server_status_client(c);
|
server_status_client(fj->client);
|
||||||
fj->status = 0;
|
fj->status = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_debug("%s: %s: %s", __func__, fj->cmd, fj->out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find a job. */
|
/* Find a job. */
|
||||||
static char *
|
static char *
|
||||||
format_job_get(struct format_tree *ft, const char *cmd)
|
format_job_get(struct format_tree *ft, const char *cmd)
|
||||||
{
|
{
|
||||||
|
struct format_job_tree *jobs;
|
||||||
struct format_job fj0, *fj;
|
struct format_job fj0, *fj;
|
||||||
time_t t;
|
time_t t;
|
||||||
char *expanded;
|
char *expanded;
|
||||||
int force;
|
int force;
|
||||||
|
|
||||||
|
if (ft->client == NULL)
|
||||||
|
jobs = &format_jobs;
|
||||||
|
else if (ft->client->jobs != NULL)
|
||||||
|
jobs = ft->client->jobs;
|
||||||
|
else {
|
||||||
|
jobs = ft->client->jobs = xmalloc(sizeof *ft->client->jobs);
|
||||||
|
RB_INIT(jobs);
|
||||||
|
}
|
||||||
|
|
||||||
fj0.tag = ft->tag;
|
fj0.tag = ft->tag;
|
||||||
fj0.cmd = cmd;
|
fj0.cmd = cmd;
|
||||||
if ((fj = RB_FIND(format_job_tree, &format_jobs, &fj0)) == NULL) {
|
if ((fj = RB_FIND(format_job_tree, jobs, &fj0)) == NULL) {
|
||||||
fj = xcalloc(1, sizeof *fj);
|
fj = xcalloc(1, sizeof *fj);
|
||||||
|
fj->client = ft->client;
|
||||||
fj->tag = ft->tag;
|
fj->tag = ft->tag;
|
||||||
fj->cmd = xstrdup(cmd);
|
fj->cmd = xstrdup(cmd);
|
||||||
fj->expanded = NULL;
|
fj->expanded = NULL;
|
||||||
|
|
||||||
xasprintf(&fj->out, "<'%s' not ready>", fj->cmd);
|
xasprintf(&fj->out, "<'%s' not ready>", fj->cmd);
|
||||||
|
|
||||||
RB_INSERT(format_job_tree, &format_jobs, fj);
|
RB_INSERT(format_job_tree, jobs, fj);
|
||||||
}
|
}
|
||||||
|
|
||||||
expanded = format_expand(ft, cmd);
|
expanded = format_expand(ft, cmd);
|
||||||
@@ -271,13 +313,14 @@ format_job_get(struct format_tree *ft, const char *cmd)
|
|||||||
|
|
||||||
t = time(NULL);
|
t = time(NULL);
|
||||||
if (fj->job == NULL && (force || fj->last != t)) {
|
if (fj->job == NULL && (force || fj->last != t)) {
|
||||||
fj->job = job_run(expanded, NULL, NULL, format_job_callback,
|
fj->job = job_run(expanded, NULL, NULL, format_job_update,
|
||||||
NULL, fj);
|
format_job_complete, NULL, fj);
|
||||||
if (fj->job == NULL) {
|
if (fj->job == NULL) {
|
||||||
free(fj->out);
|
free(fj->out);
|
||||||
xasprintf(&fj->out, "<'%s' didn't start>", fj->cmd);
|
xasprintf(&fj->out, "<'%s' didn't start>", fj->cmd);
|
||||||
}
|
}
|
||||||
fj->last = t;
|
fj->last = t;
|
||||||
|
fj->updated = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ft->flags & FORMAT_STATUS)
|
if (ft->flags & FORMAT_STATUS)
|
||||||
@@ -289,17 +332,16 @@ format_job_get(struct format_tree *ft, const char *cmd)
|
|||||||
|
|
||||||
/* Remove old jobs. */
|
/* Remove old jobs. */
|
||||||
static void
|
static void
|
||||||
format_job_timer(__unused int fd, __unused short events, __unused void *arg)
|
format_job_tidy(struct format_job_tree *jobs, int force)
|
||||||
{
|
{
|
||||||
struct format_job *fj, *fj1;
|
struct format_job *fj, *fj1;
|
||||||
time_t now;
|
time_t now;
|
||||||
struct timeval tv = { .tv_sec = 60 };
|
|
||||||
|
|
||||||
now = time(NULL);
|
now = time(NULL);
|
||||||
RB_FOREACH_SAFE(fj, format_job_tree, &format_jobs, fj1) {
|
RB_FOREACH_SAFE(fj, format_job_tree, jobs, fj1) {
|
||||||
if (fj->last > now || now - fj->last < 3600)
|
if (!force && (fj->last > now || now - fj->last < 3600))
|
||||||
continue;
|
continue;
|
||||||
RB_REMOVE(format_job_tree, &format_jobs, fj);
|
RB_REMOVE(format_job_tree, jobs, fj);
|
||||||
|
|
||||||
log_debug("%s: %s", __func__, fj->cmd);
|
log_debug("%s: %s", __func__, fj->cmd);
|
||||||
|
|
||||||
@@ -312,6 +354,29 @@ format_job_timer(__unused int fd, __unused short events, __unused void *arg)
|
|||||||
|
|
||||||
free(fj);
|
free(fj);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove old jobs for client. */
|
||||||
|
void
|
||||||
|
format_lost_client(struct client *c)
|
||||||
|
{
|
||||||
|
if (c->jobs != NULL)
|
||||||
|
format_job_tidy(c->jobs, 1);
|
||||||
|
free(c->jobs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove old jobs periodically. */
|
||||||
|
static void
|
||||||
|
format_job_timer(__unused int fd, __unused short events, __unused void *arg)
|
||||||
|
{
|
||||||
|
struct client *c;
|
||||||
|
struct timeval tv = { .tv_sec = 60 };
|
||||||
|
|
||||||
|
format_job_tidy(&format_jobs, 0);
|
||||||
|
TAILQ_FOREACH(c, &clients, entry) {
|
||||||
|
if (c->jobs != NULL)
|
||||||
|
format_job_tidy(c->jobs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
evtimer_del(&format_job_event);
|
evtimer_del(&format_job_event);
|
||||||
evtimer_add(&format_job_event, &tv);
|
evtimer_add(&format_job_event, &tv);
|
||||||
@@ -357,7 +422,7 @@ format_cb_session_alerts(struct format_tree *ft, struct format_entry *fe)
|
|||||||
{
|
{
|
||||||
struct session *s = ft->s;
|
struct session *s = ft->s;
|
||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
char alerts[256], tmp[16];
|
char alerts[1024], tmp[16];
|
||||||
|
|
||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
return;
|
return;
|
||||||
@@ -381,6 +446,48 @@ format_cb_session_alerts(struct format_tree *ft, struct format_entry *fe)
|
|||||||
fe->value = xstrdup(alerts);
|
fe->value = xstrdup(alerts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Callback for session_stack. */
|
||||||
|
static void
|
||||||
|
format_cb_session_stack(struct format_tree *ft, struct format_entry *fe)
|
||||||
|
{
|
||||||
|
struct session *s = ft->s;
|
||||||
|
struct winlink *wl;
|
||||||
|
char result[1024], tmp[16];
|
||||||
|
|
||||||
|
if (s == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
xsnprintf(result, sizeof result, "%u", s->curw->idx);
|
||||||
|
TAILQ_FOREACH(wl, &s->lastw, sentry) {
|
||||||
|
xsnprintf(tmp, sizeof tmp, "%u", wl->idx);
|
||||||
|
|
||||||
|
if (*result != '\0')
|
||||||
|
strlcat(result, ",", sizeof result);
|
||||||
|
strlcat(result, tmp, sizeof result);
|
||||||
|
}
|
||||||
|
fe->value = xstrdup(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Callback for window_stack_index. */
|
||||||
|
static void
|
||||||
|
format_cb_window_stack_index(struct format_tree *ft, struct format_entry *fe)
|
||||||
|
{
|
||||||
|
struct session *s = ft->wl->session;
|
||||||
|
struct winlink *wl;
|
||||||
|
u_int idx;
|
||||||
|
|
||||||
|
idx = 0;
|
||||||
|
TAILQ_FOREACH(wl, &s->lastw, sentry) {
|
||||||
|
idx++;
|
||||||
|
if (wl == ft->wl)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (wl != NULL)
|
||||||
|
xasprintf(&fe->value, "%u", idx);
|
||||||
|
else
|
||||||
|
fe->value = xstrdup("0");
|
||||||
|
}
|
||||||
|
|
||||||
/* Callback for window_layout. */
|
/* Callback for window_layout. */
|
||||||
static void
|
static void
|
||||||
format_cb_window_layout(struct format_tree *ft, struct format_entry *fe)
|
format_cb_window_layout(struct format_tree *ft, struct format_entry *fe)
|
||||||
@@ -523,7 +630,7 @@ format_merge(struct format_tree *ft, struct format_tree *from)
|
|||||||
|
|
||||||
/* Create a new tree. */
|
/* Create a new tree. */
|
||||||
struct format_tree *
|
struct format_tree *
|
||||||
format_create(struct cmdq_item *item, int tag, int flags)
|
format_create(struct client *c, struct cmdq_item *item, int tag, int flags)
|
||||||
{
|
{
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
|
|
||||||
@@ -535,6 +642,11 @@ format_create(struct cmdq_item *item, int tag, int flags)
|
|||||||
ft = xcalloc(1, sizeof *ft);
|
ft = xcalloc(1, sizeof *ft);
|
||||||
RB_INIT(&ft->tree);
|
RB_INIT(&ft->tree);
|
||||||
|
|
||||||
|
if (c != NULL) {
|
||||||
|
ft->client = c;
|
||||||
|
ft->client->references++;
|
||||||
|
}
|
||||||
|
|
||||||
ft->tag = tag;
|
ft->tag = tag;
|
||||||
ft->flags = flags;
|
ft->flags = flags;
|
||||||
|
|
||||||
@@ -545,10 +657,12 @@ format_create(struct cmdq_item *item, int tag, int flags)
|
|||||||
format_add(ft, "socket_path", "%s", socket_path);
|
format_add(ft, "socket_path", "%s", socket_path);
|
||||||
format_add_tv(ft, "start_time", &start_time);
|
format_add_tv(ft, "start_time", &start_time);
|
||||||
|
|
||||||
if (item != NULL && item->cmd != NULL)
|
if (item != NULL) {
|
||||||
format_add(ft, "command", "%s", item->cmd->entry->name);
|
if (item->cmd != NULL)
|
||||||
if (item != NULL && item->formats != NULL)
|
format_add(ft, "command", "%s", item->cmd->entry->name);
|
||||||
format_merge(ft, item->formats);
|
if (item->shared != NULL && item->shared->formats != NULL)
|
||||||
|
format_merge(ft, item->shared->formats);
|
||||||
|
}
|
||||||
|
|
||||||
return (ft);
|
return (ft);
|
||||||
}
|
}
|
||||||
@@ -566,6 +680,8 @@ format_free(struct format_tree *ft)
|
|||||||
free(fe);
|
free(fe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ft->client != NULL)
|
||||||
|
server_client_unref(ft->client);
|
||||||
free(ft);
|
free(ft);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1088,7 +1204,10 @@ format_single(struct cmdq_item *item, const char *fmt, struct client *c,
|
|||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
char *expanded;
|
char *expanded;
|
||||||
|
|
||||||
ft = format_create(item, FORMAT_NONE, 0);
|
if (item != NULL)
|
||||||
|
ft = format_create(item->client, item, FORMAT_NONE, 0);
|
||||||
|
else
|
||||||
|
ft = format_create(NULL, item, FORMAT_NONE, 0);
|
||||||
format_defaults(ft, c, s, wl, wp);
|
format_defaults(ft, c, s, wl, wp);
|
||||||
|
|
||||||
expanded = format_expand(ft, fmt);
|
expanded = format_expand(ft, fmt);
|
||||||
@@ -1112,8 +1231,8 @@ format_defaults(struct format_tree *ft, struct client *c, struct session *s,
|
|||||||
format_defaults_client(ft, c);
|
format_defaults_client(ft, c);
|
||||||
if (s != NULL)
|
if (s != NULL)
|
||||||
format_defaults_session(ft, s);
|
format_defaults_session(ft, s);
|
||||||
if (s != NULL && wl != NULL)
|
if (wl != NULL)
|
||||||
format_defaults_winlink(ft, s, wl);
|
format_defaults_winlink(ft, wl);
|
||||||
if (wp != NULL)
|
if (wp != NULL)
|
||||||
format_defaults_pane(ft, wp);
|
format_defaults_pane(ft, wp);
|
||||||
}
|
}
|
||||||
@@ -1145,6 +1264,7 @@ format_defaults_session(struct format_tree *ft, struct session *s)
|
|||||||
format_add(ft, "session_many_attached", "%d", s->attached > 1);
|
format_add(ft, "session_many_attached", "%d", s->attached > 1);
|
||||||
|
|
||||||
format_add_cb(ft, "session_alerts", format_cb_session_alerts);
|
format_add_cb(ft, "session_alerts", format_cb_session_alerts);
|
||||||
|
format_add_cb(ft, "session_stack", format_cb_session_stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set default format keys for a client. */
|
/* Set default format keys for a client. */
|
||||||
@@ -1174,7 +1294,9 @@ format_defaults_client(struct format_tree *ft, struct client *c)
|
|||||||
|
|
||||||
format_add_tv(ft, "client_created", &c->creation_time);
|
format_add_tv(ft, "client_created", &c->creation_time);
|
||||||
format_add_tv(ft, "client_activity", &c->activity_time);
|
format_add_tv(ft, "client_activity", &c->activity_time);
|
||||||
format_add(ft, "client_written", "%zu", tty->written);
|
|
||||||
|
format_add(ft, "client_written", "%zu", c->written);
|
||||||
|
format_add(ft, "client_discarded", "%zu", c->discarded);
|
||||||
|
|
||||||
name = server_client_get_key_table(c);
|
name = server_client_get_key_table(c);
|
||||||
if (strcmp(c->keytable->name, name) == 0)
|
if (strcmp(c->keytable->name, name) == 0)
|
||||||
@@ -1222,21 +1344,20 @@ format_defaults_window(struct format_tree *ft, struct window *w)
|
|||||||
|
|
||||||
/* Set default format keys for a winlink. */
|
/* Set default format keys for a winlink. */
|
||||||
static void
|
static void
|
||||||
format_defaults_winlink(struct format_tree *ft, struct session *s,
|
format_defaults_winlink(struct format_tree *ft, struct winlink *wl)
|
||||||
struct winlink *wl)
|
|
||||||
{
|
{
|
||||||
|
struct session *s = wl->session;
|
||||||
struct window *w = wl->window;
|
struct window *w = wl->window;
|
||||||
char *flags;
|
|
||||||
|
|
||||||
if (ft->w == NULL)
|
if (ft->w == NULL)
|
||||||
ft->w = wl->window;
|
ft->w = wl->window;
|
||||||
|
ft->wl = wl;
|
||||||
flags = window_printable_flags(s, wl);
|
|
||||||
|
|
||||||
format_defaults_window(ft, w);
|
format_defaults_window(ft, w);
|
||||||
|
|
||||||
format_add(ft, "window_index", "%d", wl->idx);
|
format_add(ft, "window_index", "%d", wl->idx);
|
||||||
format_add(ft, "window_flags", "%s", flags);
|
format_add_cb(ft, "window_stack_index", format_cb_window_stack_index);
|
||||||
|
format_add(ft, "window_flags", "%s", window_printable_flags(wl));
|
||||||
format_add(ft, "window_active", "%d", wl == s->curw);
|
format_add(ft, "window_active", "%d", wl == s->curw);
|
||||||
|
|
||||||
format_add(ft, "window_bell_flag", "%d",
|
format_add(ft, "window_bell_flag", "%d",
|
||||||
@@ -1248,8 +1369,6 @@ format_defaults_winlink(struct format_tree *ft, struct session *s,
|
|||||||
format_add(ft, "window_last_flag", "%d",
|
format_add(ft, "window_last_flag", "%d",
|
||||||
!!(wl == TAILQ_FIRST(&s->lastw)));
|
!!(wl == TAILQ_FIRST(&s->lastw)));
|
||||||
format_add(ft, "window_linked", "%d", session_is_linked(s, wl->window));
|
format_add(ft, "window_linked", "%d", session_is_linked(s, wl->window));
|
||||||
|
|
||||||
free(flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set default format keys for a window pane. */
|
/* Set default format keys for a window pane. */
|
||||||
@@ -1292,8 +1411,13 @@ format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
format_add(ft, "pane_in_mode", "%d", wp->screen != &wp->base);
|
format_add(ft, "pane_in_mode", "%d", wp->screen != &wp->base);
|
||||||
|
if (wp->mode != NULL)
|
||||||
|
format_add(ft, "pane_mode", "%s", wp->mode->name);
|
||||||
|
|
||||||
format_add(ft, "pane_synchronized", "%d",
|
format_add(ft, "pane_synchronized", "%d",
|
||||||
!!options_get_number(wp->window->options, "synchronize-panes"));
|
!!options_get_number(wp->window->options, "synchronize-panes"));
|
||||||
|
format_add(ft, "pane_search_string", "%s",
|
||||||
|
window_copy_search_string(wp));
|
||||||
|
|
||||||
format_add(ft, "pane_tty", "%s", wp->tty);
|
format_add(ft, "pane_tty", "%s", wp->tty);
|
||||||
format_add(ft, "pane_pid", "%ld", (long) wp->pid);
|
format_add(ft, "pane_pid", "%ld", (long) wp->pid);
|
||||||
|
|||||||
69
grid.c
69
grid.c
@@ -89,7 +89,7 @@ grid_need_extended_cell(const struct grid_cell_entry *gce,
|
|||||||
return (1);
|
return (1);
|
||||||
if (gc->data.size != 1 || gc->data.width != 1)
|
if (gc->data.size != 1 || gc->data.width != 1)
|
||||||
return (1);
|
return (1);
|
||||||
if ((gc->fg & COLOUR_FLAG_RGB) ||(gc->bg & COLOUR_FLAG_RGB))
|
if ((gc->fg & COLOUR_FLAG_RGB) || (gc->bg & COLOUR_FLAG_RGB))
|
||||||
return (1);
|
return (1);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@@ -472,7 +472,7 @@ grid_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny, u_int bg)
|
|||||||
gd->linedata[yy].cellsize = px;
|
gd->linedata[yy].cellsize = px;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
grid_expand_line(gd, yy, px + nx, bg);
|
grid_expand_line(gd, yy, px + nx, 8); /* default bg first */
|
||||||
for (xx = px; xx < px + nx; xx++)
|
for (xx = px; xx < px + nx; xx++)
|
||||||
grid_clear_cell(gd, xx, yy, bg);
|
grid_clear_cell(gd, xx, yy, bg);
|
||||||
}
|
}
|
||||||
@@ -675,8 +675,7 @@ grid_string_cells_code(const struct grid_cell *lastgc,
|
|||||||
{
|
{
|
||||||
int oldc[64], newc[64], s[128];
|
int oldc[64], newc[64], s[128];
|
||||||
size_t noldc, nnewc, n, i;
|
size_t noldc, nnewc, n, i;
|
||||||
u_int attr = gc->attr;
|
u_int attr = gc->attr, lastattr = lastgc->attr;
|
||||||
u_int lastattr = lastgc->attr;
|
|
||||||
char tmp[64];
|
char tmp[64];
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@@ -708,23 +707,7 @@ grid_string_cells_code(const struct grid_cell *lastgc,
|
|||||||
s[n++] = attrs[i].code;
|
s[n++] = attrs[i].code;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the foreground colour changed, append its parameters. */
|
/* Write the attributes. */
|
||||||
nnewc = grid_string_cells_fg(gc, newc);
|
|
||||||
noldc = grid_string_cells_fg(lastgc, oldc);
|
|
||||||
if (nnewc != noldc || memcmp(newc, oldc, nnewc * sizeof newc[0]) != 0) {
|
|
||||||
for (i = 0; i < nnewc; i++)
|
|
||||||
s[n++] = newc[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the background colour changed, append its parameters. */
|
|
||||||
nnewc = grid_string_cells_bg(gc, newc);
|
|
||||||
noldc = grid_string_cells_bg(lastgc, oldc);
|
|
||||||
if (nnewc != noldc || memcmp(newc, oldc, nnewc * sizeof newc[0]) != 0) {
|
|
||||||
for (i = 0; i < nnewc; i++)
|
|
||||||
s[n++] = newc[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If there are any parameters, append an SGR code. */
|
|
||||||
*buf = '\0';
|
*buf = '\0';
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
if (escape_c0)
|
if (escape_c0)
|
||||||
@@ -741,16 +724,56 @@ grid_string_cells_code(const struct grid_cell *lastgc,
|
|||||||
strlcat(buf, "m", len);
|
strlcat(buf, "m", len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the foreground colour changed, write its parameters. */
|
||||||
|
nnewc = grid_string_cells_fg(gc, newc);
|
||||||
|
noldc = grid_string_cells_fg(lastgc, oldc);
|
||||||
|
if (nnewc != noldc ||
|
||||||
|
memcmp(newc, oldc, nnewc * sizeof newc[0]) != 0 ||
|
||||||
|
(n != 0 && s[0] == 0)) {
|
||||||
|
if (escape_c0)
|
||||||
|
strlcat(buf, "\\033[", len);
|
||||||
|
else
|
||||||
|
strlcat(buf, "\033[", len);
|
||||||
|
for (i = 0; i < nnewc; i++) {
|
||||||
|
if (i + 1 < nnewc)
|
||||||
|
xsnprintf(tmp, sizeof tmp, "%d;", newc[i]);
|
||||||
|
else
|
||||||
|
xsnprintf(tmp, sizeof tmp, "%d", newc[i]);
|
||||||
|
strlcat(buf, tmp, len);
|
||||||
|
}
|
||||||
|
strlcat(buf, "m", len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the background colour changed, append its parameters. */
|
||||||
|
nnewc = grid_string_cells_bg(gc, newc);
|
||||||
|
noldc = grid_string_cells_bg(lastgc, oldc);
|
||||||
|
if (nnewc != noldc ||
|
||||||
|
memcmp(newc, oldc, nnewc * sizeof newc[0]) != 0 ||
|
||||||
|
(n != 0 && s[0] == 0)) {
|
||||||
|
if (escape_c0)
|
||||||
|
strlcat(buf, "\\033[", len);
|
||||||
|
else
|
||||||
|
strlcat(buf, "\033[", len);
|
||||||
|
for (i = 0; i < nnewc; i++) {
|
||||||
|
if (i + 1 < nnewc)
|
||||||
|
xsnprintf(tmp, sizeof tmp, "%d;", newc[i]);
|
||||||
|
else
|
||||||
|
xsnprintf(tmp, sizeof tmp, "%d", newc[i]);
|
||||||
|
strlcat(buf, tmp, len);
|
||||||
|
}
|
||||||
|
strlcat(buf, "m", len);
|
||||||
|
}
|
||||||
|
|
||||||
/* Append shift in/shift out if needed. */
|
/* Append shift in/shift out if needed. */
|
||||||
if ((attr & GRID_ATTR_CHARSET) && !(lastattr & GRID_ATTR_CHARSET)) {
|
if ((attr & GRID_ATTR_CHARSET) && !(lastattr & GRID_ATTR_CHARSET)) {
|
||||||
if (escape_c0)
|
if (escape_c0)
|
||||||
strlcat(buf, "\\016", len); /* SO */
|
strlcat(buf, "\\016", len); /* SO */
|
||||||
else
|
else
|
||||||
strlcat(buf, "\016", len); /* SO */
|
strlcat(buf, "\016", len); /* SO */
|
||||||
}
|
}
|
||||||
if (!(attr & GRID_ATTR_CHARSET) && (lastattr & GRID_ATTR_CHARSET)) {
|
if (!(attr & GRID_ATTR_CHARSET) && (lastattr & GRID_ATTR_CHARSET)) {
|
||||||
if (escape_c0)
|
if (escape_c0)
|
||||||
strlcat(buf, "\\017", len); /* SI */
|
strlcat(buf, "\\017", len); /* SI */
|
||||||
else
|
else
|
||||||
strlcat(buf, "\017", len); /* SI */
|
strlcat(buf, "\017", len); /* SI */
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,6 +200,7 @@ input_key(struct window_pane *wp, key_code key, struct mouse_event *m)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
key &= ~KEYC_XTERM;
|
||||||
|
|
||||||
/* Otherwise look the key up in the table. */
|
/* Otherwise look the key up in the table. */
|
||||||
for (i = 0; i < nitems(input_keys); i++) {
|
for (i = 0; i < nitems(input_keys); i++) {
|
||||||
|
|||||||
5
input.c
5
input.c
@@ -1308,7 +1308,8 @@ input_csi_dispatch(struct input_ctx *ictx)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case INPUT_CSI_ECH:
|
case INPUT_CSI_ECH:
|
||||||
screen_write_clearcharacter(sctx, input_get(ictx, 0, 1, 1));
|
screen_write_clearcharacter(sctx, input_get(ictx, 0, 1, 1),
|
||||||
|
ictx->cell.cell.bg);
|
||||||
break;
|
break;
|
||||||
case INPUT_CSI_DCH:
|
case INPUT_CSI_DCH:
|
||||||
screen_write_deletecharacter(sctx, input_get(ictx, 0, 1, 1),
|
screen_write_deletecharacter(sctx, input_get(ictx, 0, 1, 1),
|
||||||
@@ -2011,7 +2012,7 @@ input_utf8_close(struct input_ctx *ictx)
|
|||||||
(int)ud->size, ud->data, ud->width);
|
(int)ud->size, ud->data, ud->width);
|
||||||
|
|
||||||
utf8_copy(&ictx->cell.cell.data, ud);
|
utf8_copy(&ictx->cell.cell.data, ud);
|
||||||
screen_write_cell(&ictx->ctx, &ictx->cell.cell);
|
screen_write_collect_add(&ictx->ctx, &ictx->cell.cell);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|||||||
56
job.c
56
job.c
@@ -32,8 +32,9 @@
|
|||||||
* output.
|
* output.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void job_callback(struct bufferevent *, short, void *);
|
static void job_read_callback(struct bufferevent *, void *);
|
||||||
static void job_write_callback(struct bufferevent *, void *);
|
static void job_write_callback(struct bufferevent *, void *);
|
||||||
|
static void job_error_callback(struct bufferevent *, short, void *);
|
||||||
|
|
||||||
/* All jobs list. */
|
/* All jobs list. */
|
||||||
struct joblist all_jobs = LIST_HEAD_INITIALIZER(all_jobs);
|
struct joblist all_jobs = LIST_HEAD_INITIALIZER(all_jobs);
|
||||||
@@ -41,7 +42,8 @@ struct joblist all_jobs = LIST_HEAD_INITIALIZER(all_jobs);
|
|||||||
/* Start a job running, if it isn't already. */
|
/* Start a job running, if it isn't already. */
|
||||||
struct job *
|
struct job *
|
||||||
job_run(const char *cmd, struct session *s, const char *cwd,
|
job_run(const char *cmd, struct session *s, const char *cwd,
|
||||||
void (*callbackfn)(struct job *), void (*freefn)(void *), void *data)
|
job_update_cb updatecb, job_complete_cb completecb, job_free_cb freecb,
|
||||||
|
void *data)
|
||||||
{
|
{
|
||||||
struct job *job;
|
struct job *job;
|
||||||
struct environ *env;
|
struct environ *env;
|
||||||
@@ -52,7 +54,12 @@ job_run(const char *cmd, struct session *s, const char *cwd,
|
|||||||
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, out) != 0)
|
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, out) != 0)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
env = environ_for_session(s);
|
/*
|
||||||
|
* Do not set TERM during .tmux.conf, it is nice to be able to use
|
||||||
|
* if-shell to decide on default-terminal based on outside TERM.
|
||||||
|
*/
|
||||||
|
env = environ_for_session(s, !cfg_finished);
|
||||||
|
|
||||||
switch (pid = fork()) {
|
switch (pid = fork()) {
|
||||||
case -1:
|
case -1:
|
||||||
environ_free(env);
|
environ_free(env);
|
||||||
@@ -103,17 +110,18 @@ job_run(const char *cmd, struct session *s, const char *cwd,
|
|||||||
job->pid = pid;
|
job->pid = pid;
|
||||||
job->status = 0;
|
job->status = 0;
|
||||||
|
|
||||||
LIST_INSERT_HEAD(&all_jobs, job, lentry);
|
LIST_INSERT_HEAD(&all_jobs, job, entry);
|
||||||
|
|
||||||
job->callbackfn = callbackfn;
|
job->updatecb = updatecb;
|
||||||
job->freefn = freefn;
|
job->completecb = completecb;
|
||||||
|
job->freecb = freecb;
|
||||||
job->data = data;
|
job->data = data;
|
||||||
|
|
||||||
job->fd = out[0];
|
job->fd = out[0];
|
||||||
setblocking(job->fd, 0);
|
setblocking(job->fd, 0);
|
||||||
|
|
||||||
job->event = bufferevent_new(job->fd, NULL, job_write_callback,
|
job->event = bufferevent_new(job->fd, job_read_callback,
|
||||||
job_callback, job);
|
job_write_callback, job_error_callback, job);
|
||||||
bufferevent_enable(job->event, EV_READ|EV_WRITE);
|
bufferevent_enable(job->event, EV_READ|EV_WRITE);
|
||||||
|
|
||||||
log_debug("run job %p: %s, pid %ld", job, job->cmd, (long) job->pid);
|
log_debug("run job %p: %s, pid %ld", job, job->cmd, (long) job->pid);
|
||||||
@@ -126,11 +134,11 @@ job_free(struct job *job)
|
|||||||
{
|
{
|
||||||
log_debug("free job %p: %s", job, job->cmd);
|
log_debug("free job %p: %s", job, job->cmd);
|
||||||
|
|
||||||
LIST_REMOVE(job, lentry);
|
LIST_REMOVE(job, entry);
|
||||||
free(job->cmd);
|
free(job->cmd);
|
||||||
|
|
||||||
if (job->freefn != NULL && job->data != NULL)
|
if (job->freecb != NULL && job->data != NULL)
|
||||||
job->freefn(job->data);
|
job->freecb(job->data);
|
||||||
|
|
||||||
if (job->pid != -1)
|
if (job->pid != -1)
|
||||||
kill(job->pid, SIGTERM);
|
kill(job->pid, SIGTERM);
|
||||||
@@ -142,7 +150,21 @@ job_free(struct job *job)
|
|||||||
free(job);
|
free(job);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called when output buffer falls below low watermark (default is 0). */
|
/* Job buffer read callback. */
|
||||||
|
static void
|
||||||
|
job_read_callback(__unused struct bufferevent *bufev, void *data)
|
||||||
|
{
|
||||||
|
struct job *job = data;
|
||||||
|
|
||||||
|
if (job->updatecb != NULL)
|
||||||
|
job->updatecb (job);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Job buffer write callback. Fired when the buffer falls below watermark
|
||||||
|
* (default is empty). If all the data has been written, disable the write
|
||||||
|
* event.
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
job_write_callback(__unused struct bufferevent *bufev, void *data)
|
job_write_callback(__unused struct bufferevent *bufev, void *data)
|
||||||
{
|
{
|
||||||
@@ -160,7 +182,7 @@ job_write_callback(__unused struct bufferevent *bufev, void *data)
|
|||||||
|
|
||||||
/* Job buffer error callback. */
|
/* Job buffer error callback. */
|
||||||
static void
|
static void
|
||||||
job_callback(__unused struct bufferevent *bufev, __unused short events,
|
job_error_callback(__unused struct bufferevent *bufev, __unused short events,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
struct job *job = data;
|
struct job *job = data;
|
||||||
@@ -168,8 +190,8 @@ job_callback(__unused struct bufferevent *bufev, __unused short events,
|
|||||||
log_debug("job error %p: %s, pid %ld", job, job->cmd, (long) job->pid);
|
log_debug("job error %p: %s, pid %ld", job, job->cmd, (long) job->pid);
|
||||||
|
|
||||||
if (job->state == JOB_DEAD) {
|
if (job->state == JOB_DEAD) {
|
||||||
if (job->callbackfn != NULL)
|
if (job->completecb != NULL)
|
||||||
job->callbackfn(job);
|
job->completecb(job);
|
||||||
job_free(job);
|
job_free(job);
|
||||||
} else {
|
} else {
|
||||||
bufferevent_disable(job->event, EV_READ);
|
bufferevent_disable(job->event, EV_READ);
|
||||||
@@ -186,8 +208,8 @@ job_died(struct job *job, int status)
|
|||||||
job->status = status;
|
job->status = status;
|
||||||
|
|
||||||
if (job->state == JOB_CLOSED) {
|
if (job->state == JOB_CLOSED) {
|
||||||
if (job->callbackfn != NULL)
|
if (job->completecb != NULL)
|
||||||
job->callbackfn(job);
|
job->completecb(job);
|
||||||
job_free(job);
|
job_free(job);
|
||||||
} else {
|
} else {
|
||||||
job->pid = -1;
|
job->pid = -1;
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ key_bindings_unref_table(struct key_table *table)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
key_bindings_add(const char *name, key_code key, int can_repeat,
|
key_bindings_add(const char *name, key_code key, int repeat,
|
||||||
struct cmd_list *cmdlist)
|
struct cmd_list *cmdlist)
|
||||||
{
|
{
|
||||||
struct key_table *table;
|
struct key_table *table;
|
||||||
@@ -92,7 +92,7 @@ key_bindings_add(const char *name, key_code key, int can_repeat,
|
|||||||
|
|
||||||
table = key_bindings_get_table(name, 1);
|
table = key_bindings_get_table(name, 1);
|
||||||
|
|
||||||
bd_find.key = key;
|
bd_find.key = (key & ~KEYC_XTERM);
|
||||||
bd = RB_FIND(key_bindings, &table->key_bindings, &bd_find);
|
bd = RB_FIND(key_bindings, &table->key_bindings, &bd_find);
|
||||||
if (bd != NULL) {
|
if (bd != NULL) {
|
||||||
RB_REMOVE(key_bindings, &table->key_bindings, bd);
|
RB_REMOVE(key_bindings, &table->key_bindings, bd);
|
||||||
@@ -100,11 +100,12 @@ key_bindings_add(const char *name, key_code key, int can_repeat,
|
|||||||
free(bd);
|
free(bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
bd = xmalloc(sizeof *bd);
|
bd = xcalloc(1, sizeof *bd);
|
||||||
bd->key = key;
|
bd->key = key;
|
||||||
RB_INSERT(key_bindings, &table->key_bindings, bd);
|
RB_INSERT(key_bindings, &table->key_bindings, bd);
|
||||||
|
|
||||||
bd->can_repeat = can_repeat;
|
if (repeat)
|
||||||
|
bd->flags |= KEY_BINDING_REPEAT;
|
||||||
bd->cmdlist = cmdlist;
|
bd->cmdlist = cmdlist;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,7 +119,7 @@ key_bindings_remove(const char *name, key_code key)
|
|||||||
if (table == NULL)
|
if (table == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bd_find.key = key;
|
bd_find.key = (key & ~KEYC_XTERM);
|
||||||
bd = RB_FIND(key_bindings, &table->key_bindings, &bd_find);
|
bd = RB_FIND(key_bindings, &table->key_bindings, &bd_find);
|
||||||
if (bd == NULL)
|
if (bd == NULL)
|
||||||
return;
|
return;
|
||||||
@@ -415,7 +416,8 @@ key_bindings_dispatch(struct key_binding *bd, struct client *c,
|
|||||||
cmdq_append(c, cmdq_get_callback(key_bindings_read_only, NULL));
|
cmdq_append(c, cmdq_get_callback(key_bindings_read_only, NULL));
|
||||||
else {
|
else {
|
||||||
item = cmdq_get_command(bd->cmdlist, fs, m, 0);
|
item = cmdq_get_command(bd->cmdlist, fs, m, 0);
|
||||||
item->repeat = bd->can_repeat;
|
if (bd->flags & KEY_BINDING_REPEAT)
|
||||||
|
item->shared->flags |= CMDQ_SHARED_REPEAT;
|
||||||
cmdq_append(c, item);
|
cmdq_append(c, item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
names.c
2
names.c
@@ -124,7 +124,7 @@ format_window_name(struct window *w)
|
|||||||
const char *fmt;
|
const char *fmt;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
ft = format_create(NULL, FORMAT_WINDOW|w->id, 0);
|
ft = format_create(NULL, NULL, FORMAT_WINDOW|w->id, 0);
|
||||||
format_defaults_window(ft, w);
|
format_defaults_window(ft, w);
|
||||||
format_defaults_pane(ft, w->active);
|
format_defaults_pane(ft, w->active);
|
||||||
|
|
||||||
|
|||||||
37
notify.c
37
notify.c
@@ -43,9 +43,9 @@ notify_hook(struct cmdq_item *item, struct notify_entry *ne)
|
|||||||
struct session *s = ne->session;
|
struct session *s = ne->session;
|
||||||
struct window *w = ne->window;
|
struct window *w = ne->window;
|
||||||
|
|
||||||
cmd_find_clear_state(&fs, NULL, 0);
|
cmd_find_clear_state(&fs, 0);
|
||||||
if (cmd_find_empty_state(&ne->fs) || !cmd_find_valid_state(&ne->fs))
|
if (cmd_find_empty_state(&ne->fs) || !cmd_find_valid_state(&ne->fs))
|
||||||
cmd_find_current(&fs, item, CMD_FIND_QUIET);
|
cmd_find_from_nothing(&fs);
|
||||||
else
|
else
|
||||||
cmd_find_copy_state(&fs, &ne->fs);
|
cmd_find_copy_state(&fs, &ne->fs);
|
||||||
|
|
||||||
@@ -78,8 +78,12 @@ notify_callback(struct cmdq_item *item, void *data)
|
|||||||
|
|
||||||
log_debug("%s: %s", __func__, ne->name);
|
log_debug("%s: %s", __func__, ne->name);
|
||||||
|
|
||||||
|
if (strcmp(ne->name, "pane-mode-changed") == 0)
|
||||||
|
control_notify_pane_mode_changed(ne->pane);
|
||||||
if (strcmp(ne->name, "window-layout-changed") == 0)
|
if (strcmp(ne->name, "window-layout-changed") == 0)
|
||||||
control_notify_window_layout_changed(ne->window);
|
control_notify_window_layout_changed(ne->window);
|
||||||
|
if (strcmp(ne->name, "window-pane-changed") == 0)
|
||||||
|
control_notify_window_pane_changed(ne->window);
|
||||||
if (strcmp(ne->name, "window-unlinked") == 0)
|
if (strcmp(ne->name, "window-unlinked") == 0)
|
||||||
control_notify_window_unlinked(ne->session, ne->window);
|
control_notify_window_unlinked(ne->session, ne->window);
|
||||||
if (strcmp(ne->name, "window-linked") == 0)
|
if (strcmp(ne->name, "window-linked") == 0)
|
||||||
@@ -94,18 +98,20 @@ notify_callback(struct cmdq_item *item, void *data)
|
|||||||
control_notify_session_created(ne->session);
|
control_notify_session_created(ne->session);
|
||||||
if (strcmp(ne->name, "session-closed") == 0)
|
if (strcmp(ne->name, "session-closed") == 0)
|
||||||
control_notify_session_closed(ne->session);
|
control_notify_session_closed(ne->session);
|
||||||
|
if (strcmp(ne->name, "session-window-changed") == 0)
|
||||||
|
control_notify_session_window_changed(ne->session);
|
||||||
|
|
||||||
notify_hook(item, ne);
|
notify_hook(item, ne);
|
||||||
|
|
||||||
if (ne->client != NULL)
|
if (ne->client != NULL)
|
||||||
server_client_unref(ne->client);
|
server_client_unref(ne->client);
|
||||||
if (ne->session != NULL)
|
if (ne->session != NULL)
|
||||||
session_unref(ne->session);
|
session_remove_ref(ne->session, __func__);
|
||||||
if (ne->window != NULL)
|
if (ne->window != NULL)
|
||||||
window_remove_ref(ne->window);
|
window_remove_ref(ne->window, __func__);
|
||||||
|
|
||||||
if (ne->fs.s != NULL)
|
if (ne->fs.s != NULL)
|
||||||
session_unref(ne->fs.s);
|
session_remove_ref(ne->fs.s, __func__);
|
||||||
|
|
||||||
free((void *)ne->name);
|
free((void *)ne->name);
|
||||||
free(ne);
|
free(ne);
|
||||||
@@ -135,13 +141,13 @@ notify_add(const char *name, struct cmd_find_state *fs, struct client *c,
|
|||||||
if (c != NULL)
|
if (c != NULL)
|
||||||
c->references++;
|
c->references++;
|
||||||
if (s != NULL)
|
if (s != NULL)
|
||||||
s->references++;
|
session_add_ref(s, __func__);
|
||||||
if (w != NULL)
|
if (w != NULL)
|
||||||
w->references++;
|
window_add_ref(w, __func__);
|
||||||
|
|
||||||
cmd_find_copy_state(&ne->fs, fs);
|
cmd_find_copy_state(&ne->fs, fs);
|
||||||
if (ne->fs.s != NULL)
|
if (ne->fs.s != NULL) /* cmd_find_valid_state needs session */
|
||||||
ne->fs.s->references++; /* cmd_find_valid_state need session */
|
session_add_ref(ne->fs.s, __func__);
|
||||||
|
|
||||||
new_item = cmdq_get_callback(notify_callback, ne);
|
new_item = cmdq_get_callback(notify_callback, ne);
|
||||||
cmdq_append(NULL, new_item);
|
cmdq_append(NULL, new_item);
|
||||||
@@ -163,10 +169,7 @@ notify_client(const char *name, struct client *c)
|
|||||||
{
|
{
|
||||||
struct cmd_find_state fs;
|
struct cmd_find_state fs;
|
||||||
|
|
||||||
if (c->session != NULL)
|
cmd_find_from_client(&fs, c);
|
||||||
cmd_find_from_session(&fs, c->session);
|
|
||||||
else
|
|
||||||
cmd_find_current(&fs, NULL, CMD_FIND_QUIET);
|
|
||||||
notify_add(name, &fs, c, NULL, NULL, NULL);
|
notify_add(name, &fs, c, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,17 +181,17 @@ notify_session(const char *name, struct session *s)
|
|||||||
if (session_alive(s))
|
if (session_alive(s))
|
||||||
cmd_find_from_session(&fs, s);
|
cmd_find_from_session(&fs, s);
|
||||||
else
|
else
|
||||||
cmd_find_current(&fs, NULL, CMD_FIND_QUIET);
|
cmd_find_from_nothing(&fs);
|
||||||
notify_add(name, &fs, NULL, s, NULL, NULL);
|
notify_add(name, &fs, NULL, s, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
notify_winlink(const char *name, struct session *s, struct winlink *wl)
|
notify_winlink(const char *name, struct winlink *wl)
|
||||||
{
|
{
|
||||||
struct cmd_find_state fs;
|
struct cmd_find_state fs;
|
||||||
|
|
||||||
cmd_find_from_winlink(&fs, s, wl);
|
cmd_find_from_winlink(&fs, wl);
|
||||||
notify_add(name, &fs, NULL, s, wl->window, NULL);
|
notify_add(name, &fs, NULL, wl->session, wl->window, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -433,7 +433,7 @@ options_match(const char *s, int *idx, int* ambiguous)
|
|||||||
|
|
||||||
if (*name == '@') {
|
if (*name == '@') {
|
||||||
*ambiguous = 0;
|
*ambiguous = 0;
|
||||||
return (xstrdup(name));
|
return (name);
|
||||||
}
|
}
|
||||||
|
|
||||||
found = NULL;
|
found = NULL;
|
||||||
|
|||||||
88
pty.c
88
pty.c
@@ -1,88 +0,0 @@
|
|||||||
/* $OpenBSD$ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
|
||||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#ifdef __OpenBSD__
|
|
||||||
#include <sys/tty.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <termios.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "compat.h"
|
|
||||||
|
|
||||||
int pty_open(int *);
|
|
||||||
pid_t pty_fork(int, int *, char *, size_t, struct winsize *);
|
|
||||||
|
|
||||||
#ifdef __OpenBSD__
|
|
||||||
int
|
|
||||||
pty_open(int *fd)
|
|
||||||
{
|
|
||||||
*fd = open(PATH_PTMDEV, O_RDWR|O_CLOEXEC);
|
|
||||||
if (*fd < 0)
|
|
||||||
return (-1);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
int
|
|
||||||
pty_open(__unused int *fd)
|
|
||||||
{
|
|
||||||
*fd = -1;
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __OpenBSD__
|
|
||||||
pid_t
|
|
||||||
pty_fork(int ptmfd, int *fd, char *name, size_t namelen, struct winsize *ws)
|
|
||||||
{
|
|
||||||
struct ptmget ptm;
|
|
||||||
pid_t pid;
|
|
||||||
|
|
||||||
if (ioctl(ptmfd, PTMGET, &ptm) == -1)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
strlcpy(name, ptm.sn, namelen);
|
|
||||||
ioctl(ptm.sfd, TIOCSWINSZ, ws);
|
|
||||||
|
|
||||||
switch (pid = fork()) {
|
|
||||||
case -1:
|
|
||||||
close(ptm.cfd);
|
|
||||||
close(ptm.sfd);
|
|
||||||
return (-1);
|
|
||||||
case 0:
|
|
||||||
close(ptm.cfd);
|
|
||||||
login_tty(ptm.sfd);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
*fd = ptm.cfd;
|
|
||||||
close(ptm.sfd);
|
|
||||||
return (pid);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
pid_t
|
|
||||||
pty_fork(__unused int ptmfd, int *fd, char *name, __unused size_t namelen,
|
|
||||||
struct winsize *ws)
|
|
||||||
{
|
|
||||||
return (forkpty(fd, name, NULL, ws));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
9
regress/Makefile
Normal file
9
regress/Makefile
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
TESTS!= echo *.sh
|
||||||
|
|
||||||
|
.PHONY: all $(TESTS)
|
||||||
|
.NOTPARALLEL: all $(TESTS)
|
||||||
|
|
||||||
|
all: $(TESTS)
|
||||||
|
|
||||||
|
$(TESTS):
|
||||||
|
sh $*.sh
|
||||||
24
regress/capture-pane-sgr0.sh
Normal file
24
regress/capture-pane-sgr0.sh
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# 884
|
||||||
|
# capture-pane should send colours after SGR 0
|
||||||
|
|
||||||
|
PATH=/bin:/usr/bin
|
||||||
|
TERM=screen
|
||||||
|
|
||||||
|
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||||
|
TMUX="$TEST_TMUX -Ltest"
|
||||||
|
$TMUX kill-server 2>/dev/null
|
||||||
|
|
||||||
|
TMP=$(mktemp)
|
||||||
|
trap "rm -f $TMP" 0 1 15
|
||||||
|
|
||||||
|
$TMUX -f/dev/null new -d \
|
||||||
|
"printf '\033[31;42;1mabc\033[0;31mdef'; $TMUX capturep -peS0 -E0 >$TMP"
|
||||||
|
sleep 1
|
||||||
|
printf '\033[1m\033[31m\033[42mabc\033[0m\033[31m\033[49mdef\033[39m\n'| \
|
||||||
|
cmp - $TMP || exit 1
|
||||||
|
|
||||||
|
$TMUX has 2>/dev/null && exit 1
|
||||||
|
|
||||||
|
exit 0
|
||||||
30
regress/if-shell-TERM.sh
Normal file
30
regress/if-shell-TERM.sh
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# 882
|
||||||
|
# TERM should come from outside tmux for if-shell from the config file
|
||||||
|
|
||||||
|
PATH=/bin:/usr/bin
|
||||||
|
TERM=screen
|
||||||
|
|
||||||
|
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||||
|
TMUX="$TEST_TMUX -Ltest"
|
||||||
|
$TMUX kill-server 2>/dev/null
|
||||||
|
|
||||||
|
TMP=$(mktemp)
|
||||||
|
trap "rm -f $TMP" 0 1 15
|
||||||
|
|
||||||
|
cat <<EOF >$TMP
|
||||||
|
if '[ "\$TERM" = "xterm" ]' \
|
||||||
|
'set -g default-terminal "vt220"' \
|
||||||
|
'set -g default-terminal "ansi"'
|
||||||
|
EOF
|
||||||
|
|
||||||
|
TERM=xterm $TMUX -f$TMP new -d "echo \"#\$TERM\" >>$TMP" || exit 1
|
||||||
|
sleep 1 && [ "$(tail -1 $TMP)" = "#vt220" ] || exit 1
|
||||||
|
|
||||||
|
TERM=screen $TMUX -f$TMP new -d "echo \"#\$TERM\" >>$TMP" || exit 1
|
||||||
|
sleep 1 && [ "$(tail -1 $TMP)" = "#ansi" ] || exit 1
|
||||||
|
|
||||||
|
$TMUX has 2>/dev/null && exit 1
|
||||||
|
|
||||||
|
exit 0
|
||||||
26
regress/if-shell-error.sh
Normal file
26
regress/if-shell-error.sh
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# 883
|
||||||
|
# if-shell with an error should not core :-)
|
||||||
|
|
||||||
|
PATH=/bin:/usr/bin
|
||||||
|
TERM=screen
|
||||||
|
|
||||||
|
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||||
|
TMUX="$TEST_TMUX -Ltest"
|
||||||
|
$TMUX kill-server 2>/dev/null
|
||||||
|
|
||||||
|
TMP=$(mktemp)
|
||||||
|
trap "rm -f $TMP" 0 1 15
|
||||||
|
|
||||||
|
cat <<EOF >$TMP
|
||||||
|
if 'true' 'wibble wobble'
|
||||||
|
EOF
|
||||||
|
|
||||||
|
$TMUX -f$TMP new -d || exit 1
|
||||||
|
sleep 1
|
||||||
|
E=$($TMUX display -p '#{pane_in_mode}')
|
||||||
|
$TMUX kill-server 2>/dev/null
|
||||||
|
[ "$E" = "1" ] || exit 1
|
||||||
|
|
||||||
|
exit 0
|
||||||
25
regress/if-shell-nested.sh
Normal file
25
regress/if-shell-nested.sh
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# 882
|
||||||
|
# tmux inside if-shell itself should work
|
||||||
|
|
||||||
|
PATH=/bin:/usr/bin
|
||||||
|
TERM=screen
|
||||||
|
|
||||||
|
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||||
|
TMUX="$TEST_TMUX -Ltest"
|
||||||
|
$TMUX kill-server 2>/dev/null
|
||||||
|
|
||||||
|
TMP=$(mktemp)
|
||||||
|
trap "rm -f $TMP" 0 1 15
|
||||||
|
|
||||||
|
cat <<EOF >$TMP
|
||||||
|
if '$TMUX run "true"' 'set -s @done yes'
|
||||||
|
EOF
|
||||||
|
|
||||||
|
TERM=xterm $TMUX -f$TMP new -d "$TMUX show -vs @done >>$TMP" || exit 1
|
||||||
|
sleep 1 && [ "$(tail -1 $TMP)" = "yes" ] || exit 1
|
||||||
|
|
||||||
|
$TMUX has 2>/dev/null && exit 1
|
||||||
|
|
||||||
|
exit 0
|
||||||
21
regress/kill-session-process-exit.sh
Normal file
21
regress/kill-session-process-exit.sh
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# when we kill a session, processes running in it should be killed
|
||||||
|
|
||||||
|
PATH=/bin:/usr/bin
|
||||||
|
TERM=screen
|
||||||
|
|
||||||
|
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||||
|
TMUX="$TEST_TMUX -Ltest"
|
||||||
|
$TMUX kill-server 2>/dev/null
|
||||||
|
|
||||||
|
$TMUX new -d 'sleep 1000' || exit 1
|
||||||
|
P=$($TMUX display -pt0:0.0 '#{pane_pid}')
|
||||||
|
$TMUX new -d || exit 1
|
||||||
|
sleep 1
|
||||||
|
$TMUX kill-session -t0:
|
||||||
|
sleep 1
|
||||||
|
kill -0 $P 2>/dev/null && exit 1
|
||||||
|
$TMUX kill-server 2>/dev/null
|
||||||
|
|
||||||
|
exit 0
|
||||||
27
regress/new-session-base-index.sh
Normal file
27
regress/new-session-base-index.sh
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# new session base-index
|
||||||
|
|
||||||
|
PATH=/bin:/usr/bin
|
||||||
|
TERM=screen
|
||||||
|
|
||||||
|
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||||
|
TMUX="$TEST_TMUX -Ltest"
|
||||||
|
$TMUX kill-server 2>/dev/null
|
||||||
|
|
||||||
|
TMP=$(mktemp)
|
||||||
|
trap "rm -f $TMP" 0 1 15
|
||||||
|
|
||||||
|
cat <<EOF >$TMP
|
||||||
|
set -g base-index 100
|
||||||
|
new
|
||||||
|
set base-index 200
|
||||||
|
neww
|
||||||
|
EOF
|
||||||
|
|
||||||
|
$TMUX -f$TMP start
|
||||||
|
echo $($TMUX lsw -F'#{window_index}') >$TMP
|
||||||
|
(echo "100 200"|cmp -s - $TMP) || exit 1
|
||||||
|
$TMUX kill-server 2>/dev/null
|
||||||
|
|
||||||
|
exit 0
|
||||||
25
regress/new-session-command.sh
Normal file
25
regress/new-session-command.sh
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# new session command
|
||||||
|
|
||||||
|
PATH=/bin:/usr/bin
|
||||||
|
TERM=screen
|
||||||
|
|
||||||
|
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||||
|
TMUX="$TEST_TMUX -Ltest"
|
||||||
|
$TMUX kill-server 2>/dev/null
|
||||||
|
|
||||||
|
TMP=$(mktemp)
|
||||||
|
trap "rm -f $TMP" 0 1 15
|
||||||
|
|
||||||
|
cat <<EOF >$TMP
|
||||||
|
new sleep 101
|
||||||
|
new -- sleep 102
|
||||||
|
new "sleep 103"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
$TMUX -f$TMP start
|
||||||
|
[ $($TMUX ls|wc -l) -eq 3 ] || exit 1
|
||||||
|
$TMUX kill-server 2>/dev/null
|
||||||
|
|
||||||
|
exit 0
|
||||||
66
regress/new-session-environment.sh
Normal file
66
regress/new-session-environment.sh
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# new session environment
|
||||||
|
|
||||||
|
PATH=/bin:/usr/bin
|
||||||
|
TERM=screen
|
||||||
|
|
||||||
|
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||||
|
TMUX="$TEST_TMUX -Ltest"
|
||||||
|
$TMUX kill-server 2>/dev/null
|
||||||
|
|
||||||
|
TMP=$(mktemp)
|
||||||
|
OUT=$(mktemp)
|
||||||
|
SCRIPT=$(mktemp)
|
||||||
|
trap "rm -f $TMP $OUT $SCRIPT" 0 1 15
|
||||||
|
|
||||||
|
cat <<EOF >$SCRIPT
|
||||||
|
(
|
||||||
|
echo TERM=\$TERM
|
||||||
|
echo PWD=\$(pwd)
|
||||||
|
echo PATH=\$PATH
|
||||||
|
echo SHELL=\$SHELL
|
||||||
|
echo TEST=\$TEST
|
||||||
|
) >$OUT
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat <<EOF >$TMP
|
||||||
|
new -- /bin/sh $SCRIPT
|
||||||
|
EOF
|
||||||
|
|
||||||
|
(cd /; env -i TERM=ansi TEST=test1 PATH=1 SHELL=/bin/sh \
|
||||||
|
$TMUX -f$TMP start) || exit 1
|
||||||
|
sleep 1
|
||||||
|
(cat <<EOF|cmp -s - $OUT) || exit 1
|
||||||
|
TERM=screen
|
||||||
|
PWD=/
|
||||||
|
PATH=1
|
||||||
|
SHELL=/bin/sh
|
||||||
|
TEST=test1
|
||||||
|
EOF
|
||||||
|
|
||||||
|
(cd /; env -i TERM=ansi TEST=test2 PATH=2 SHELL=/bin/sh \
|
||||||
|
$TMUX -f$TMP new -d -- /bin/sh $SCRIPT) || exit 1
|
||||||
|
sleep 1
|
||||||
|
(cat <<EOF|cmp -s - $OUT) || exit 1
|
||||||
|
TERM=screen
|
||||||
|
PWD=/
|
||||||
|
PATH=2
|
||||||
|
SHELL=/bin/sh
|
||||||
|
TEST=test2
|
||||||
|
EOF
|
||||||
|
|
||||||
|
(cd /; env -i TERM=ansi TEST=test3 PATH=3 SHELL=/bin/sh \
|
||||||
|
$TMUX -f/dev/null new -d source $TMP) || exit 1
|
||||||
|
sleep 1
|
||||||
|
(cat <<EOF|cmp -s - $OUT) || exit 1
|
||||||
|
TERM=screen
|
||||||
|
PWD=/
|
||||||
|
PATH=2
|
||||||
|
SHELL=/bin/sh
|
||||||
|
TEST=test2
|
||||||
|
EOF
|
||||||
|
|
||||||
|
$TMUX kill-server 2>/dev/null
|
||||||
|
|
||||||
|
exit 0
|
||||||
25
regress/new-session-no-client.sh
Normal file
25
regress/new-session-no-client.sh
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# 869
|
||||||
|
# new with no client (that is, from the config file) should imply -d and
|
||||||
|
# not attach
|
||||||
|
|
||||||
|
PATH=/bin:/usr/bin
|
||||||
|
TERM=screen
|
||||||
|
|
||||||
|
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||||
|
TMUX="$TEST_TMUX -Ltest"
|
||||||
|
$TMUX kill-server 2>/dev/null
|
||||||
|
|
||||||
|
TMP=$(mktemp)
|
||||||
|
trap "rm -f $TMP" 0 1 15
|
||||||
|
|
||||||
|
cat <<EOF >$TMP
|
||||||
|
new -stest
|
||||||
|
EOF
|
||||||
|
|
||||||
|
$TMUX -f$TMP start || exit 1
|
||||||
|
sleep 1 && $TMUX has -t=test: || exit 1
|
||||||
|
$TMUX kill-server 2>/dev/null
|
||||||
|
|
||||||
|
exit 0
|
||||||
26
regress/new-window-command.sh
Normal file
26
regress/new-window-command.sh
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# new session command
|
||||||
|
|
||||||
|
PATH=/bin:/usr/bin
|
||||||
|
TERM=screen
|
||||||
|
|
||||||
|
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||||
|
TMUX="$TEST_TMUX -Ltest"
|
||||||
|
$TMUX kill-server 2>/dev/null
|
||||||
|
|
||||||
|
TMP=$(mktemp)
|
||||||
|
trap "rm -f $TMP" 0 1 15
|
||||||
|
|
||||||
|
cat <<EOF >$TMP
|
||||||
|
new
|
||||||
|
neww sleep 101
|
||||||
|
neww -- sleep 102
|
||||||
|
neww "sleep 103"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
$TMUX -f$TMP start
|
||||||
|
[ $($TMUX lsw|wc -l) -eq 4 ] || exit 1
|
||||||
|
$TMUX kill-server 2>/dev/null
|
||||||
|
|
||||||
|
exit 0
|
||||||
@@ -280,7 +280,7 @@ screen_redraw_make_pane_status(struct client *c, struct window *w,
|
|||||||
|
|
||||||
fmt = options_get_string(w->options, "pane-border-format");
|
fmt = options_get_string(w->options, "pane-border-format");
|
||||||
|
|
||||||
ft = format_create(NULL, FORMAT_PANE|wp->id, 0);
|
ft = format_create(c, NULL, FORMAT_PANE|wp->id, 0);
|
||||||
format_defaults(ft, c, NULL, NULL, wp);
|
format_defaults(ft, c, NULL, NULL, wp);
|
||||||
|
|
||||||
memcpy(&old, &wp->status_screen, sizeof old);
|
memcpy(&old, &wp->status_screen, sizeof old);
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ static const struct grid_cell screen_write_pad_cell = {
|
|||||||
|
|
||||||
struct screen_write_collect_item {
|
struct screen_write_collect_item {
|
||||||
u_int x;
|
u_int x;
|
||||||
|
int wrapped;
|
||||||
|
|
||||||
u_int used;
|
u_int used;
|
||||||
char data[256];
|
char data[256];
|
||||||
@@ -386,6 +387,8 @@ screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx)
|
|||||||
{
|
{
|
||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
|
|
||||||
|
memset(ttyctx, 0, sizeof *ttyctx);
|
||||||
|
|
||||||
ttyctx->wp = ctx->wp;
|
ttyctx->wp = ctx->wp;
|
||||||
|
|
||||||
ttyctx->ocx = s->cx;
|
ttyctx->ocx = s->cx;
|
||||||
@@ -605,7 +608,7 @@ screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg)
|
|||||||
|
|
||||||
/* Clear nx characters. */
|
/* Clear nx characters. */
|
||||||
void
|
void
|
||||||
screen_write_clearcharacter(struct screen_write_ctx *ctx, u_int nx)
|
screen_write_clearcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg)
|
||||||
{
|
{
|
||||||
struct screen *s = ctx->s;
|
struct screen *s = ctx->s;
|
||||||
struct tty_ctx ttyctx;
|
struct tty_ctx ttyctx;
|
||||||
@@ -622,8 +625,9 @@ screen_write_clearcharacter(struct screen_write_ctx *ctx, u_int nx)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
screen_write_initctx(ctx, &ttyctx);
|
screen_write_initctx(ctx, &ttyctx);
|
||||||
|
ttyctx.bg = bg;
|
||||||
|
|
||||||
grid_view_clear(s->grid, s->cx, s->cy, nx, 1, 8);
|
grid_view_clear(s->grid, s->cx, s->cy, nx, 1, bg);
|
||||||
|
|
||||||
screen_write_collect_flush(ctx, 0);
|
screen_write_collect_flush(ctx, 0);
|
||||||
ttyctx.num = nx;
|
ttyctx.num = nx;
|
||||||
@@ -942,9 +946,9 @@ screen_write_clearstartofscreen(struct screen_write_ctx *ctx, u_int bg)
|
|||||||
if (s->cy > 0)
|
if (s->cy > 0)
|
||||||
grid_view_clear(s->grid, 0, 0, sx, s->cy, bg);
|
grid_view_clear(s->grid, 0, 0, sx, s->cy, bg);
|
||||||
if (s->cx > sx - 1)
|
if (s->cx > sx - 1)
|
||||||
grid_view_clear(s->grid, 0, s->cy, sx, 1, 8);
|
grid_view_clear(s->grid, 0, s->cy, sx, 1, bg);
|
||||||
else
|
else
|
||||||
grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1, 8);
|
grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1, bg);
|
||||||
|
|
||||||
screen_write_collect_clear(ctx, 0, s->cy);
|
screen_write_collect_clear(ctx, 0, s->cy);
|
||||||
screen_write_collect_flush(ctx, 0);
|
screen_write_collect_flush(ctx, 0);
|
||||||
@@ -1054,6 +1058,7 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only)
|
|||||||
screen_write_cursormove(ctx, ci->x, y);
|
screen_write_cursormove(ctx, ci->x, y);
|
||||||
screen_write_initctx(ctx, &ttyctx);
|
screen_write_initctx(ctx, &ttyctx);
|
||||||
ttyctx.cell = &ci->gc;
|
ttyctx.cell = &ci->gc;
|
||||||
|
ttyctx.wrapped = ci->wrapped;
|
||||||
ttyctx.ptr = ci->data;
|
ttyctx.ptr = ci->data;
|
||||||
ttyctx.num = ci->used;
|
ttyctx.num = ci->used;
|
||||||
tty_write(tty_cmd_cells, &ttyctx);
|
tty_write(tty_cmd_cells, &ttyctx);
|
||||||
@@ -1113,7 +1118,7 @@ screen_write_collect_add(struct screen_write_ctx *ctx,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
collect = 1;
|
collect = 1;
|
||||||
if (gc->data.width != 1)
|
if (gc->data.width != 1 || gc->data.size != 1)
|
||||||
collect = 0;
|
collect = 0;
|
||||||
else if (gc->attr & GRID_ATTR_CHARSET)
|
else if (gc->attr & GRID_ATTR_CHARSET)
|
||||||
collect = 0;
|
collect = 0;
|
||||||
@@ -1133,13 +1138,15 @@ screen_write_collect_add(struct screen_write_ctx *ctx,
|
|||||||
|
|
||||||
if (s->cx > sx - 1 || ctx->item->used > sx - 1 - s->cx)
|
if (s->cx > sx - 1 || ctx->item->used > sx - 1 - s->cx)
|
||||||
screen_write_collect_end(ctx);
|
screen_write_collect_end(ctx);
|
||||||
|
ci = ctx->item; /* may have changed */
|
||||||
|
|
||||||
if (s->cx > sx - 1) {
|
if (s->cx > sx - 1) {
|
||||||
log_debug("%s: wrapped at %u,%u", __func__, s->cx, s->cy);
|
log_debug("%s: wrapped at %u,%u", __func__, s->cx, s->cy);
|
||||||
|
ci->wrapped = 1;
|
||||||
screen_write_linefeed(ctx, 1);
|
screen_write_linefeed(ctx, 1);
|
||||||
s->cx = 0;
|
s->cx = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ci = ctx->item; /* may have changed */
|
|
||||||
if (ci->used == 0)
|
if (ci->used == 0)
|
||||||
memcpy(&ci->gc, gc, sizeof ci->gc);
|
memcpy(&ci->gc, gc, sizeof ci->gc);
|
||||||
ci->data[ci->used++] = gc->data.data[0];
|
ci->data[ci->used++] = gc->data.data[0];
|
||||||
@@ -1312,12 +1319,12 @@ screen_write_combine(struct screen_write_ctx *ctx, const struct utf8_data *ud,
|
|||||||
fatalx("UTF-8 data empty");
|
fatalx("UTF-8 data empty");
|
||||||
|
|
||||||
/* Retrieve the previous cell. */
|
/* Retrieve the previous cell. */
|
||||||
for (n = 1; n < s->cx; n++) {
|
for (n = 1; n <= s->cx; n++) {
|
||||||
grid_view_get_cell(gd, s->cx - n, s->cy, &gc);
|
grid_view_get_cell(gd, s->cx - n, s->cy, &gc);
|
||||||
if (~gc.flags & GRID_FLAG_PADDING)
|
if (~gc.flags & GRID_FLAG_PADDING)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (n == s->cx)
|
if (n > s->cx)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
*xx = s->cx - n;
|
*xx = s->cx - n;
|
||||||
|
|
||||||
|
|||||||
176
server-client.c
176
server-client.c
@@ -47,7 +47,7 @@ static void server_client_dispatch_command(struct client *, struct imsg *);
|
|||||||
static void server_client_dispatch_identify(struct client *, struct imsg *);
|
static void server_client_dispatch_identify(struct client *, struct imsg *);
|
||||||
static void server_client_dispatch_shell(struct client *);
|
static void server_client_dispatch_shell(struct client *);
|
||||||
|
|
||||||
/* Idenfity mode callback. */
|
/* Identify mode callback. */
|
||||||
static void
|
static void
|
||||||
server_client_callback_identify(__unused int fd, __unused short events, void *data)
|
server_client_callback_identify(__unused int fd, __unused short events, void *data)
|
||||||
{
|
{
|
||||||
@@ -136,11 +136,11 @@ server_client_get_key_table(struct client *c)
|
|||||||
return (name);
|
return (name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is this client using the default key table? */
|
/* Is this table the default key table? */
|
||||||
int
|
static int
|
||||||
server_client_is_default_key_table(struct client *c)
|
server_client_is_default_key_table(struct client *c, struct key_table *table)
|
||||||
{
|
{
|
||||||
return (strcmp(c->keytable->name, server_client_get_key_table(c)) == 0);
|
return (strcmp(table->name, server_client_get_key_table(c)) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a new client. */
|
/* Create a new client. */
|
||||||
@@ -281,6 +281,7 @@ server_client_lost(struct client *c)
|
|||||||
free(c->prompt_string);
|
free(c->prompt_string);
|
||||||
free(c->prompt_buffer);
|
free(c->prompt_buffer);
|
||||||
|
|
||||||
|
format_lost_client(c);
|
||||||
environ_free(c->environ);
|
environ_free(c->environ);
|
||||||
|
|
||||||
proc_remove_peer(c->peer);
|
proc_remove_peer(c->peer);
|
||||||
@@ -323,15 +324,30 @@ server_client_free(__unused int fd, __unused short events, void *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Suspend a client. */
|
||||||
|
void
|
||||||
|
server_client_suspend(struct client *c)
|
||||||
|
{
|
||||||
|
struct session *s = c->session;
|
||||||
|
|
||||||
|
if (s == NULL || (c->flags & CLIENT_DETACHING))
|
||||||
|
return;
|
||||||
|
|
||||||
|
tty_stop_tty(&c->tty);
|
||||||
|
c->flags |= CLIENT_SUSPENDED;
|
||||||
|
proc_send(c->peer, MSG_SUSPEND, -1, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Detach a client. */
|
/* Detach a client. */
|
||||||
void
|
void
|
||||||
server_client_detach(struct client *c, enum msgtype msgtype)
|
server_client_detach(struct client *c, enum msgtype msgtype)
|
||||||
{
|
{
|
||||||
struct session *s = c->session;
|
struct session *s = c->session;
|
||||||
|
|
||||||
if (s == NULL)
|
if (s == NULL || (c->flags & CLIENT_DETACHING))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
c->flags |= CLIENT_DETACHING;
|
||||||
notify_client("client-detached", c);
|
notify_client("client-detached", c);
|
||||||
proc_send_s(c->peer, msgtype, s->name);
|
proc_send_s(c->peer, msgtype, s->name);
|
||||||
}
|
}
|
||||||
@@ -776,8 +792,7 @@ server_client_handle_key(struct client *c, key_code key)
|
|||||||
struct window *w;
|
struct window *w;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
const char *name;
|
struct key_table *table, *first;
|
||||||
struct key_table *table;
|
|
||||||
struct key_binding bd_find, *bd;
|
struct key_binding bd_find, *bd;
|
||||||
int xtimeout;
|
int xtimeout;
|
||||||
struct cmd_find_state fs;
|
struct cmd_find_state fs;
|
||||||
@@ -840,10 +855,9 @@ server_client_handle_key(struct client *c, key_code key)
|
|||||||
m->valid = 0;
|
m->valid = 0;
|
||||||
|
|
||||||
/* Find affected pane. */
|
/* Find affected pane. */
|
||||||
if (KEYC_IS_MOUSE(key) && m->valid)
|
if (!KEYC_IS_MOUSE(key) || cmd_find_from_mouse(&fs, m) != 0)
|
||||||
wp = cmd_mouse_pane(m, NULL, NULL);
|
cmd_find_from_session(&fs, s);
|
||||||
else
|
wp = fs.wp;
|
||||||
wp = w->active;
|
|
||||||
|
|
||||||
/* Forward mouse keys if disabled. */
|
/* Forward mouse keys if disabled. */
|
||||||
if (KEYC_IS_MOUSE(key) && !options_get_number(s->options, "mouse"))
|
if (KEYC_IS_MOUSE(key) && !options_get_number(s->options, "mouse"))
|
||||||
@@ -853,22 +867,18 @@ server_client_handle_key(struct client *c, key_code key)
|
|||||||
if (!KEYC_IS_MOUSE(key) && server_client_assume_paste(s))
|
if (!KEYC_IS_MOUSE(key) && server_client_assume_paste(s))
|
||||||
goto forward;
|
goto forward;
|
||||||
|
|
||||||
retry:
|
|
||||||
/*
|
/*
|
||||||
* Work out the current key table. If the pane is in a mode, use
|
* Work out the current key table. If the pane is in a mode, use
|
||||||
* the mode table instead of the default key table.
|
* the mode table instead of the default key table.
|
||||||
*/
|
*/
|
||||||
name = NULL;
|
if (server_client_is_default_key_table(c, c->keytable) &&
|
||||||
if (wp != NULL && wp->mode != NULL && wp->mode->key_table != NULL)
|
wp != NULL &&
|
||||||
name = wp->mode->key_table(wp);
|
wp->mode != NULL &&
|
||||||
if (name == NULL || !server_client_is_default_key_table(c))
|
wp->mode->key_table != NULL)
|
||||||
|
table = key_bindings_get_table(wp->mode->key_table(wp), 1);
|
||||||
|
else
|
||||||
table = c->keytable;
|
table = c->keytable;
|
||||||
else
|
first = table;
|
||||||
table = key_bindings_get_table(name, 1);
|
|
||||||
if (wp == NULL)
|
|
||||||
log_debug("key table %s (no pane)", table->name);
|
|
||||||
else
|
|
||||||
log_debug("key table %s (pane %%%u)", table->name, wp->id);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The prefix always takes precedence and forces a switch to the prefix
|
* The prefix always takes precedence and forces a switch to the prefix
|
||||||
@@ -882,8 +892,17 @@ retry:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
retry:
|
||||||
|
/* Log key table. */
|
||||||
|
if (wp == NULL)
|
||||||
|
log_debug("key table %s (no pane)", table->name);
|
||||||
|
else
|
||||||
|
log_debug("key table %s (pane %%%u)", table->name, wp->id);
|
||||||
|
if (c->flags & CLIENT_REPEAT)
|
||||||
|
log_debug("currently repeating");
|
||||||
|
|
||||||
/* Try to see if there is a key binding in the current table. */
|
/* Try to see if there is a key binding in the current table. */
|
||||||
bd_find.key = key;
|
bd_find.key = (key & ~KEYC_XTERM);
|
||||||
bd = RB_FIND(key_bindings, &table->key_bindings, &bd_find);
|
bd = RB_FIND(key_bindings, &table->key_bindings, &bd_find);
|
||||||
if (bd != NULL) {
|
if (bd != NULL) {
|
||||||
/*
|
/*
|
||||||
@@ -891,12 +910,15 @@ retry:
|
|||||||
* non-repeating binding was found, stop repeating and try
|
* non-repeating binding was found, stop repeating and try
|
||||||
* again in the root table.
|
* again in the root table.
|
||||||
*/
|
*/
|
||||||
if ((c->flags & CLIENT_REPEAT) && !bd->can_repeat) {
|
if ((c->flags & CLIENT_REPEAT) &&
|
||||||
|
(~bd->flags & KEY_BINDING_REPEAT)) {
|
||||||
server_client_set_key_table(c, NULL);
|
server_client_set_key_table(c, NULL);
|
||||||
c->flags &= ~CLIENT_REPEAT;
|
c->flags &= ~CLIENT_REPEAT;
|
||||||
server_status_client(c);
|
server_status_client(c);
|
||||||
|
table = c->keytable;
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
log_debug("found in key table %s", table->name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Take a reference to this table to make sure the key binding
|
* Take a reference to this table to make sure the key binding
|
||||||
@@ -909,7 +931,7 @@ retry:
|
|||||||
* the client back to the root table.
|
* the client back to the root table.
|
||||||
*/
|
*/
|
||||||
xtimeout = options_get_number(s->options, "repeat-time");
|
xtimeout = options_get_number(s->options, "repeat-time");
|
||||||
if (xtimeout != 0 && bd->can_repeat) {
|
if (xtimeout != 0 && (bd->flags & KEY_BINDING_REPEAT)) {
|
||||||
c->flags |= CLIENT_REPEAT;
|
c->flags |= CLIENT_REPEAT;
|
||||||
|
|
||||||
tv.tv_sec = xtimeout / 1000;
|
tv.tv_sec = xtimeout / 1000;
|
||||||
@@ -922,39 +944,31 @@ retry:
|
|||||||
}
|
}
|
||||||
server_status_client(c);
|
server_status_client(c);
|
||||||
|
|
||||||
/* Find default state if the pane is known. */
|
/* Execute the key binding. */
|
||||||
cmd_find_clear_state(&fs, NULL, 0);
|
|
||||||
if (wp != NULL) {
|
|
||||||
fs.s = s;
|
|
||||||
fs.wl = fs.s->curw;
|
|
||||||
fs.w = fs.wl->window;
|
|
||||||
fs.wp = wp;
|
|
||||||
cmd_find_log_state(__func__, &fs);
|
|
||||||
|
|
||||||
if (!cmd_find_valid_state(&fs))
|
|
||||||
fatalx("invalid key state");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dispatch the key binding. */
|
|
||||||
key_bindings_dispatch(bd, c, m, &fs);
|
key_bindings_dispatch(bd, c, m, &fs);
|
||||||
key_bindings_unref_table(table);
|
key_bindings_unref_table(table);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* No match in this table. If repeating, switch the client back to the
|
* No match in this table. If not in the root table or if repeating,
|
||||||
* root table and try again.
|
* switch the client back to the root table and try again.
|
||||||
*/
|
*/
|
||||||
if (c->flags & CLIENT_REPEAT) {
|
log_debug("not found in key table %s", table->name);
|
||||||
|
if (!server_client_is_default_key_table(c, table) ||
|
||||||
|
(c->flags & CLIENT_REPEAT)) {
|
||||||
server_client_set_key_table(c, NULL);
|
server_client_set_key_table(c, NULL);
|
||||||
c->flags &= ~CLIENT_REPEAT;
|
c->flags &= ~CLIENT_REPEAT;
|
||||||
server_status_client(c);
|
server_status_client(c);
|
||||||
|
table = c->keytable;
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If no match and we're not in the root table, that's it. */
|
/*
|
||||||
if (name == NULL && !server_client_is_default_key_table(c)) {
|
* No match in the root table either. If this wasn't the first table
|
||||||
log_debug("no key in key table %s", table->name);
|
* tried, don't pass the key to the pane.
|
||||||
|
*/
|
||||||
|
if (first != table) {
|
||||||
server_client_set_key_table(c, NULL);
|
server_client_set_key_table(c, NULL);
|
||||||
server_status_client(c);
|
server_status_client(c);
|
||||||
return;
|
return;
|
||||||
@@ -1209,6 +1223,14 @@ server_client_check_exit(struct client *c)
|
|||||||
c->flags &= ~CLIENT_EXIT;
|
c->flags &= ~CLIENT_EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Redraw timer callback. */
|
||||||
|
static void
|
||||||
|
server_client_redraw_timer(__unused int fd, __unused short events,
|
||||||
|
__unused void* data)
|
||||||
|
{
|
||||||
|
log_debug("redraw timer fired");
|
||||||
|
}
|
||||||
|
|
||||||
/* Check for client redraws. */
|
/* Check for client redraws. */
|
||||||
static void
|
static void
|
||||||
server_client_check_redraw(struct client *c)
|
server_client_check_redraw(struct client *c)
|
||||||
@@ -1216,19 +1238,61 @@ server_client_check_redraw(struct client *c)
|
|||||||
struct session *s = c->session;
|
struct session *s = c->session;
|
||||||
struct tty *tty = &c->tty;
|
struct tty *tty = &c->tty;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
int flags, masked;
|
int needed, flags, masked;
|
||||||
|
struct timeval tv = { .tv_usec = 1000 };
|
||||||
|
static struct event ev;
|
||||||
|
size_t left;
|
||||||
|
|
||||||
if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED))
|
if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If there is outstanding data, defer the redraw until it has been
|
||||||
|
* consumed. We can just add a timer to get out of the event loop and
|
||||||
|
* end up back here.
|
||||||
|
*/
|
||||||
|
needed = 0;
|
||||||
|
if (c->flags & CLIENT_REDRAW)
|
||||||
|
needed = 1;
|
||||||
|
else {
|
||||||
|
TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) {
|
||||||
|
if (wp->flags & PANE_REDRAW) {
|
||||||
|
needed = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (needed) {
|
||||||
|
left = EVBUFFER_LENGTH(tty->out);
|
||||||
|
if (left != 0) {
|
||||||
|
log_debug("%s: redraw deferred (%zu left)", c->name, left);
|
||||||
|
if (evtimer_initialized(&ev) && evtimer_pending(&ev, NULL))
|
||||||
|
return;
|
||||||
|
log_debug("redraw timer started");
|
||||||
|
evtimer_set(&ev, server_client_redraw_timer, NULL);
|
||||||
|
evtimer_add(&ev, &tv);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We may have got here for a single pane redraw, but
|
||||||
|
* force a full redraw next time in case other panes
|
||||||
|
* have been updated.
|
||||||
|
*/
|
||||||
|
c->flags |= CLIENT_REDRAW;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (evtimer_initialized(&ev))
|
||||||
|
evtimer_del(&ev);
|
||||||
|
log_debug("%s: redraw needed", c->name);
|
||||||
|
}
|
||||||
|
|
||||||
if (c->flags & (CLIENT_REDRAW|CLIENT_STATUS)) {
|
if (c->flags & (CLIENT_REDRAW|CLIENT_STATUS)) {
|
||||||
if (options_get_number(s->options, "set-titles"))
|
if (options_get_number(s->options, "set-titles"))
|
||||||
server_client_set_title(c);
|
server_client_set_title(c);
|
||||||
screen_redraw_update(c); /* will adjust flags */
|
screen_redraw_update(c); /* will adjust flags */
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = tty->flags & (TTY_FREEZE|TTY_NOCURSOR);
|
flags = tty->flags & (TTY_BLOCK|TTY_FREEZE|TTY_NOCURSOR);
|
||||||
tty->flags = (tty->flags & ~TTY_FREEZE) | TTY_NOCURSOR;
|
tty->flags = (tty->flags & ~(TTY_BLOCK|TTY_FREEZE)) | TTY_NOCURSOR;
|
||||||
|
|
||||||
if (c->flags & CLIENT_REDRAW) {
|
if (c->flags & CLIENT_REDRAW) {
|
||||||
tty_update_mode(tty, tty->mode, NULL);
|
tty_update_mode(tty, tty->mode, NULL);
|
||||||
@@ -1258,6 +1322,16 @@ server_client_check_redraw(struct client *c)
|
|||||||
|
|
||||||
c->flags &= ~(CLIENT_REDRAW|CLIENT_BORDERS|CLIENT_STATUS|
|
c->flags &= ~(CLIENT_REDRAW|CLIENT_BORDERS|CLIENT_STATUS|
|
||||||
CLIENT_STATUSFORCE);
|
CLIENT_STATUSFORCE);
|
||||||
|
|
||||||
|
if (needed) {
|
||||||
|
/*
|
||||||
|
* We would have deferred the redraw unless the output buffer
|
||||||
|
* was empty, so we can record how many bytes the redraw
|
||||||
|
* generated.
|
||||||
|
*/
|
||||||
|
c->redraw = EVBUFFER_LENGTH(tty->out);
|
||||||
|
log_debug("%s: redraw added %zu bytes", c->name, c->redraw);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set client title. */
|
/* Set client title. */
|
||||||
@@ -1271,7 +1345,7 @@ server_client_set_title(struct client *c)
|
|||||||
|
|
||||||
template = options_get_string(s->options, "set-titles-string");
|
template = options_get_string(s->options, "set-titles-string");
|
||||||
|
|
||||||
ft = format_create(NULL, FORMAT_NONE, 0);
|
ft = format_create(c, NULL, FORMAT_NONE, 0);
|
||||||
format_defaults(ft, c, NULL, NULL, NULL);
|
format_defaults(ft, c, NULL, NULL, NULL);
|
||||||
|
|
||||||
title = format_expand_time(ft, template, time(NULL));
|
title = format_expand_time(ft, template, time(NULL));
|
||||||
|
|||||||
25
server.c
25
server.c
@@ -62,7 +62,7 @@ static void server_child_stopped(pid_t, int);
|
|||||||
void
|
void
|
||||||
server_set_marked(struct session *s, struct winlink *wl, struct window_pane *wp)
|
server_set_marked(struct session *s, struct winlink *wl, struct window_pane *wp)
|
||||||
{
|
{
|
||||||
cmd_find_clear_state(&marked_pane, NULL, 0);
|
cmd_find_clear_state(&marked_pane, 0);
|
||||||
marked_pane.s = s;
|
marked_pane.s = s;
|
||||||
marked_pane.wl = wl;
|
marked_pane.wl = wl;
|
||||||
marked_pane.w = wl->window;
|
marked_pane.w = wl->window;
|
||||||
@@ -73,7 +73,7 @@ server_set_marked(struct session *s, struct winlink *wl, struct window_pane *wp)
|
|||||||
void
|
void
|
||||||
server_clear_marked(void)
|
server_clear_marked(void)
|
||||||
{
|
{
|
||||||
cmd_find_clear_state(&marked_pane, NULL, 0);
|
cmd_find_clear_state(&marked_pane, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is this the marked pane? */
|
/* Is this the marked pane? */
|
||||||
@@ -118,12 +118,16 @@ server_create_socket(void)
|
|||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
mask = umask(S_IXUSR|S_IXGRP|S_IRWXO);
|
mask = umask(S_IXUSR|S_IXGRP|S_IRWXO);
|
||||||
if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) == -1)
|
if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
|
||||||
|
close(fd);
|
||||||
return (-1);
|
return (-1);
|
||||||
|
}
|
||||||
umask(mask);
|
umask(mask);
|
||||||
|
|
||||||
if (listen(fd, 128) == -1)
|
if (listen(fd, 128) == -1) {
|
||||||
|
close(fd);
|
||||||
return (-1);
|
return (-1);
|
||||||
|
}
|
||||||
setblocking(fd, 0);
|
setblocking(fd, 0);
|
||||||
|
|
||||||
return (fd);
|
return (fd);
|
||||||
@@ -133,7 +137,8 @@ server_create_socket(void)
|
|||||||
int
|
int
|
||||||
server_start(struct event_base *base, int lockfd, char *lockfile)
|
server_start(struct event_base *base, int lockfd, char *lockfile)
|
||||||
{
|
{
|
||||||
int pair[2];
|
int pair[2];
|
||||||
|
struct job *job;
|
||||||
|
|
||||||
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
|
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
|
||||||
fatal("socketpair failed");
|
fatal("socketpair failed");
|
||||||
@@ -174,11 +179,15 @@ server_start(struct event_base *base, int lockfd, char *lockfile)
|
|||||||
|
|
||||||
start_cfg();
|
start_cfg();
|
||||||
|
|
||||||
status_prompt_load_history();
|
|
||||||
|
|
||||||
server_add_accept(0);
|
server_add_accept(0);
|
||||||
|
|
||||||
proc_loop(server_proc, server_loop);
|
proc_loop(server_proc, server_loop);
|
||||||
|
|
||||||
|
LIST_FOREACH(job, &all_jobs, entry) {
|
||||||
|
if (job->pid != -1)
|
||||||
|
kill(job->pid, SIGTERM);
|
||||||
|
}
|
||||||
|
|
||||||
status_prompt_save_history();
|
status_prompt_save_history();
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
@@ -399,7 +408,7 @@ server_child_exited(pid_t pid, int status)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LIST_FOREACH(job, &all_jobs, lentry) {
|
LIST_FOREACH(job, &all_jobs, entry) {
|
||||||
if (pid == job->pid) {
|
if (pid == job->pid) {
|
||||||
job_died(job, status); /* might free job */
|
job_died(job, status); /* might free job */
|
||||||
break;
|
break;
|
||||||
|
|||||||
19
session.c
19
session.c
@@ -188,13 +188,21 @@ session_create(const char *prefix, const char *name, int argc, char **argv,
|
|||||||
return (s);
|
return (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add a reference to a session. */
|
||||||
|
void
|
||||||
|
session_add_ref(struct session *s, const char *from)
|
||||||
|
{
|
||||||
|
s->references++;
|
||||||
|
log_debug("%s: %s %s, now %d", __func__, s->name, from, s->references);
|
||||||
|
}
|
||||||
|
|
||||||
/* Remove a reference from a session. */
|
/* Remove a reference from a session. */
|
||||||
void
|
void
|
||||||
session_unref(struct session *s)
|
session_remove_ref(struct session *s, const char *from)
|
||||||
{
|
{
|
||||||
log_debug("session %s has %d references", s->name, s->references);
|
|
||||||
|
|
||||||
s->references--;
|
s->references--;
|
||||||
|
log_debug("%s: %s %s, now %d", __func__, s->name, from, s->references);
|
||||||
|
|
||||||
if (s->references == 0)
|
if (s->references == 0)
|
||||||
event_once(-1, EV_TIMEOUT, session_free, s, NULL);
|
event_once(-1, EV_TIMEOUT, session_free, s, NULL);
|
||||||
}
|
}
|
||||||
@@ -247,7 +255,7 @@ session_destroy(struct session *s)
|
|||||||
|
|
||||||
free((void *)s->cwd);
|
free((void *)s->cwd);
|
||||||
|
|
||||||
session_unref(s);
|
session_remove_ref(s, __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check a session name is valid: not empty and no colons or periods. */
|
/* Check a session name is valid: not empty and no colons or periods. */
|
||||||
@@ -359,7 +367,7 @@ session_new(struct session *s, const char *name, int argc, char **argv,
|
|||||||
shell = _PATH_BSHELL;
|
shell = _PATH_BSHELL;
|
||||||
|
|
||||||
hlimit = options_get_number(s->options, "history-limit");
|
hlimit = options_get_number(s->options, "history-limit");
|
||||||
env = environ_for_session(s);
|
env = environ_for_session(s, 0);
|
||||||
w = window_create_spawn(name, argc, argv, path, shell, cwd, env, s->tio,
|
w = window_create_spawn(name, argc, argv, path, shell, cwd, env, s->tio,
|
||||||
s->sx, s->sy, hlimit, cause);
|
s->sx, s->sy, hlimit, cause);
|
||||||
if (w == NULL) {
|
if (w == NULL) {
|
||||||
@@ -544,6 +552,7 @@ session_set_current(struct session *s, struct winlink *wl)
|
|||||||
s->curw = wl;
|
s->curw = wl;
|
||||||
winlink_clear_flags(wl);
|
winlink_clear_flags(wl);
|
||||||
window_update_activity(wl->window);
|
window_update_activity(wl->window);
|
||||||
|
notify_session("session-window-changed", s);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
17
status.c
17
status.c
@@ -519,9 +519,9 @@ status_replace(struct client *c, struct winlink *wl, const char *fmt, time_t t)
|
|||||||
else
|
else
|
||||||
tag = FORMAT_NONE;
|
tag = FORMAT_NONE;
|
||||||
if (c->flags & CLIENT_STATUSFORCE)
|
if (c->flags & CLIENT_STATUSFORCE)
|
||||||
ft = format_create(NULL, tag, FORMAT_STATUS|FORMAT_FORCE);
|
ft = format_create(c, NULL, tag, FORMAT_STATUS|FORMAT_FORCE);
|
||||||
else
|
else
|
||||||
ft = format_create(NULL, tag, FORMAT_STATUS);
|
ft = format_create(c, NULL, tag, FORMAT_STATUS);
|
||||||
format_defaults(ft, c, NULL, wl, NULL);
|
format_defaults(ft, c, NULL, wl, NULL);
|
||||||
|
|
||||||
expanded = format_expand_time(ft, fmt, t);
|
expanded = format_expand_time(ft, fmt, t);
|
||||||
@@ -661,9 +661,9 @@ status_prompt_set(struct client *c, const char *msg, const char *input,
|
|||||||
{
|
{
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
time_t t;
|
time_t t;
|
||||||
char *tmp;
|
char *tmp, *cp;
|
||||||
|
|
||||||
ft = format_create(NULL, FORMAT_NONE, 0);
|
ft = format_create(c, NULL, FORMAT_NONE, 0);
|
||||||
format_defaults(ft, c, NULL, NULL, NULL);
|
format_defaults(ft, c, NULL, NULL, NULL);
|
||||||
|
|
||||||
t = time(NULL);
|
t = time(NULL);
|
||||||
@@ -690,6 +690,12 @@ status_prompt_set(struct client *c, const char *msg, const char *input,
|
|||||||
c->tty.flags |= (TTY_NOCURSOR|TTY_FREEZE);
|
c->tty.flags |= (TTY_NOCURSOR|TTY_FREEZE);
|
||||||
c->flags |= CLIENT_STATUS;
|
c->flags |= CLIENT_STATUS;
|
||||||
|
|
||||||
|
if ((flags & PROMPT_INCREMENTAL) && *tmp != '\0') {
|
||||||
|
xasprintf(&cp, "=%s", tmp);
|
||||||
|
c->prompt_callbackfn(c->prompt_data, cp, 0);
|
||||||
|
free(cp);
|
||||||
|
}
|
||||||
|
|
||||||
free(tmp);
|
free(tmp);
|
||||||
format_free(ft);
|
format_free(ft);
|
||||||
}
|
}
|
||||||
@@ -724,7 +730,7 @@ status_prompt_update(struct client *c, const char *msg, const char *input)
|
|||||||
time_t t;
|
time_t t;
|
||||||
char *tmp;
|
char *tmp;
|
||||||
|
|
||||||
ft = format_create(NULL, FORMAT_NONE, 0);
|
ft = format_create(c, NULL, FORMAT_NONE, 0);
|
||||||
format_defaults(ft, c, NULL, NULL, NULL);
|
format_defaults(ft, c, NULL, NULL, NULL);
|
||||||
|
|
||||||
t = time(NULL);
|
t = time(NULL);
|
||||||
@@ -1497,6 +1503,7 @@ status_prompt_complete(struct session *session, const char *s)
|
|||||||
out = status_prompt_complete_prefix(list, size);
|
out = status_prompt_complete_prefix(list, size);
|
||||||
if (out != NULL) {
|
if (out != NULL) {
|
||||||
xasprintf(&tmp, "-%c%s%s", copy[1], out, colon);
|
xasprintf(&tmp, "-%c%s%s", copy[1], out, colon);
|
||||||
|
free(out);
|
||||||
out = tmp;
|
out = tmp;
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
|
|||||||
29
tmux.1
29
tmux.1
@@ -3199,7 +3199,6 @@ will generate
|
|||||||
.Xr xterm 1 -style
|
.Xr xterm 1 -style
|
||||||
function key sequences; these have a number included to indicate modifiers such
|
function key sequences; these have a number included to indicate modifiers such
|
||||||
as Shift, Alt or Ctrl.
|
as Shift, Alt or Ctrl.
|
||||||
The default is off.
|
|
||||||
.El
|
.El
|
||||||
.It Xo Ic show-options
|
.It Xo Ic show-options
|
||||||
.Op Fl gqsvw
|
.Op Fl gqsvw
|
||||||
@@ -3439,7 +3438,7 @@ or
|
|||||||
.Ql !=
|
.Ql !=
|
||||||
and a colon.
|
and a colon.
|
||||||
For example
|
For example
|
||||||
.Ql #{==,#{host},myhost}
|
.Ql #{==:#{host},myhost}
|
||||||
will be replaced by
|
will be replaced by
|
||||||
.Ql 1
|
.Ql 1
|
||||||
if running on
|
if running on
|
||||||
@@ -3494,6 +3493,8 @@ does not wait for
|
|||||||
.Ql #()
|
.Ql #()
|
||||||
commands to finish; instead, the previous result from running the same command is used,
|
commands to finish; instead, the previous result from running the same command is used,
|
||||||
or a placeholder if the command has not been run before.
|
or a placeholder if the command has not been run before.
|
||||||
|
If the command hasn't exited, the most recent line of output will be used, but the status
|
||||||
|
line will not be updated more than once a second.
|
||||||
Commands are executed with the
|
Commands are executed with the
|
||||||
.Nm
|
.Nm
|
||||||
global environment set (see the
|
global environment set (see the
|
||||||
@@ -3512,6 +3513,7 @@ The following variables are available, where appropriate:
|
|||||||
.It Li "client_activity" Ta "" Ta "Integer time client last had activity"
|
.It Li "client_activity" Ta "" Ta "Integer time client last had activity"
|
||||||
.It Li "client_created" Ta "" Ta "Integer time client created"
|
.It Li "client_created" Ta "" Ta "Integer time client created"
|
||||||
.It Li "client_control_mode" Ta "" Ta "1 if client is in control mode"
|
.It Li "client_control_mode" Ta "" Ta "1 if client is in control mode"
|
||||||
|
.It Li "client_discarded" Ta "" Ta "Bytes discarded when client behind"
|
||||||
.It Li "client_height" Ta "" Ta "Height of client"
|
.It Li "client_height" Ta "" Ta "Height of client"
|
||||||
.It Li "client_key_table" Ta "" Ta "Current key table"
|
.It Li "client_key_table" Ta "" Ta "Current key table"
|
||||||
.It Li "client_last_session" Ta "" Ta "Name of the client's last session"
|
.It Li "client_last_session" Ta "" Ta "Name of the client's last session"
|
||||||
@@ -3564,8 +3566,10 @@ The following variables are available, where appropriate:
|
|||||||
.It Li "pane_input_off" Ta "" Ta "If input to pane is disabled"
|
.It Li "pane_input_off" Ta "" Ta "If input to pane is disabled"
|
||||||
.It Li "pane_index" Ta "#P" Ta "Index of pane"
|
.It Li "pane_index" Ta "#P" Ta "Index of pane"
|
||||||
.It Li "pane_left" Ta "" Ta "Left of pane"
|
.It Li "pane_left" Ta "" Ta "Left of pane"
|
||||||
|
.It Li "pane_mode" Ta "" Ta "Name of pane mode, if any."
|
||||||
.It Li "pane_pid" Ta "" Ta "PID of first process in pane"
|
.It Li "pane_pid" Ta "" Ta "PID of first process in pane"
|
||||||
.It Li "pane_right" Ta "" Ta "Right of pane"
|
.It Li "pane_right" Ta "" Ta "Right of pane"
|
||||||
|
.It Li "pane_search_string" Ta "" Ta "Last search string in copy mode"
|
||||||
.It Li "pane_start_command" Ta "" Ta "Command pane started with"
|
.It Li "pane_start_command" Ta "" Ta "Command pane started with"
|
||||||
.It Li "pane_synchronized" Ta "" Ta "If pane is synchronized"
|
.It Li "pane_synchronized" Ta "" Ta "If pane is synchronized"
|
||||||
.It Li "pane_tabs" Ta "" Ta "Pane tab positions"
|
.It Li "pane_tabs" Ta "" Ta "Pane tab positions"
|
||||||
@@ -3588,6 +3592,7 @@ The following variables are available, where appropriate:
|
|||||||
.It Li "session_id" Ta "" Ta "Unique session ID"
|
.It Li "session_id" Ta "" Ta "Unique session ID"
|
||||||
.It Li "session_many_attached" Ta "" Ta "1 if multiple clients attached"
|
.It Li "session_many_attached" Ta "" Ta "1 if multiple clients attached"
|
||||||
.It Li "session_name" Ta "#S" Ta "Name of session"
|
.It Li "session_name" Ta "#S" Ta "Name of session"
|
||||||
|
.It Li "session_stack" Ta "" Ta "Window indexes in most recent order"
|
||||||
.It Li "session_width" Ta "" Ta "Width of session"
|
.It Li "session_width" Ta "" Ta "Width of session"
|
||||||
.It Li "session_windows" Ta "" Ta "Number of windows in session"
|
.It Li "session_windows" Ta "" Ta "Number of windows in session"
|
||||||
.It Li "socket_path" Ta "" Ta "Server socket path"
|
.It Li "socket_path" Ta "" Ta "Server socket path"
|
||||||
@@ -3608,6 +3613,7 @@ The following variables are available, where appropriate:
|
|||||||
.It Li "window_name" Ta "#W" Ta "Name of window"
|
.It Li "window_name" Ta "#W" Ta "Name of window"
|
||||||
.It Li "window_panes" Ta "" Ta "Number of panes in window"
|
.It Li "window_panes" Ta "" Ta "Number of panes in window"
|
||||||
.It Li "window_silence_flag" Ta "" Ta "1 if window has silence alert"
|
.It Li "window_silence_flag" Ta "" Ta "1 if window has silence alert"
|
||||||
|
.It Li "window_stack_index" Ta "" Ta "Index in session most recent stack"
|
||||||
.It Li "window_visible_layout" Ta "" Ta "Window layout description, respecting zoomed window panes"
|
.It Li "window_visible_layout" Ta "" Ta "Window layout description, respecting zoomed window panes"
|
||||||
.It Li "window_width" Ta "" Ta "Width of window"
|
.It Li "window_width" Ta "" Ta "Width of window"
|
||||||
.It Li "window_zoomed_flag" Ta "" Ta "1 if window is zoomed"
|
.It Li "window_zoomed_flag" Ta "" Ta "1 if window is zoomed"
|
||||||
@@ -4234,6 +4240,11 @@ A notification will never occur inside an output block.
|
|||||||
.Pp
|
.Pp
|
||||||
The following notifications are defined:
|
The following notifications are defined:
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
|
.It Ic %client-session-changed Ar client Ar session-id Ar name
|
||||||
|
The client is now attached to the session with ID
|
||||||
|
.Ar session-id ,
|
||||||
|
which is named
|
||||||
|
.Ar name .
|
||||||
.It Ic %exit Op Ar reason
|
.It Ic %exit Op Ar reason
|
||||||
The
|
The
|
||||||
.Nm
|
.Nm
|
||||||
@@ -4256,6 +4267,10 @@ and the window flags are
|
|||||||
A window pane produced output.
|
A window pane produced output.
|
||||||
.Ar value
|
.Ar value
|
||||||
escapes non-printable characters and backslash as octal \\xxx.
|
escapes non-printable characters and backslash as octal \\xxx.
|
||||||
|
.It Ic %pane-mode-changed Ar pane-id
|
||||||
|
The pane with ID
|
||||||
|
.Ar pane-id
|
||||||
|
has changed mode.
|
||||||
.It Ic %session-changed Ar session-id Ar name
|
.It Ic %session-changed Ar session-id Ar name
|
||||||
The client is now attached to the session with ID
|
The client is now attached to the session with ID
|
||||||
.Ar session-id ,
|
.Ar session-id ,
|
||||||
@@ -4264,6 +4279,11 @@ which is named
|
|||||||
.It Ic %session-renamed Ar name
|
.It Ic %session-renamed Ar name
|
||||||
The current session was renamed to
|
The current session was renamed to
|
||||||
.Ar name .
|
.Ar name .
|
||||||
|
.It Ic %session-window-changed Ar session-id Ar window-id
|
||||||
|
The session with ID
|
||||||
|
.Ar session-id
|
||||||
|
changed its active window to the window with ID
|
||||||
|
.Ar window-id .
|
||||||
.It Ic %sessions-changed
|
.It Ic %sessions-changed
|
||||||
A session was created or destroyed.
|
A session was created or destroyed.
|
||||||
.It Ic %unlinked-window-add Ar window-id
|
.It Ic %unlinked-window-add Ar window-id
|
||||||
@@ -4278,6 +4298,11 @@ was linked to the current session.
|
|||||||
The window with ID
|
The window with ID
|
||||||
.Ar window-id
|
.Ar window-id
|
||||||
closed.
|
closed.
|
||||||
|
.It Ic %window-pane-changed Ar window-id Ar pane-id
|
||||||
|
The active pane in the window with ID
|
||||||
|
.Ar window-id
|
||||||
|
changed to the pane with ID
|
||||||
|
.Ar pane-id .
|
||||||
.It Ic %window-renamed Ar window-id Ar name
|
.It Ic %window-renamed Ar window-id Ar name
|
||||||
The window with ID
|
The window with ID
|
||||||
.Ar window-id
|
.Ar window-id
|
||||||
|
|||||||
7
tmux.c
7
tmux.c
@@ -22,7 +22,6 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <event.h>
|
#include <event.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <getopt.h>
|
|
||||||
#include <langinfo.h>
|
#include <langinfo.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
@@ -118,7 +117,7 @@ make_label(const char *label)
|
|||||||
uid = getuid();
|
uid = getuid();
|
||||||
|
|
||||||
if ((s = getenv("TMUX_TMPDIR")) != NULL && *s != '\0')
|
if ((s = getenv("TMUX_TMPDIR")) != NULL && *s != '\0')
|
||||||
xasprintf(&base, "%s/tmux-%u", s, uid);
|
xasprintf(&base, "%s/tmux-%ld", s, (long)uid);
|
||||||
else
|
else
|
||||||
xasprintf(&base, "%s/tmux-%ld", _PATH_TMP, (long)uid);
|
xasprintf(&base, "%s/tmux-%ld", _PATH_TMP, (long)uid);
|
||||||
|
|
||||||
@@ -261,8 +260,8 @@ main(int argc, char **argv)
|
|||||||
if (shellcmd != NULL && argc != 0)
|
if (shellcmd != NULL && argc != 0)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
if (pty_open(&ptm_fd) != 0)
|
if ((ptm_fd = getptmfd()) == -1)
|
||||||
errx(1, "open(\"/dev/ptm\"");
|
err(1, "getptmfd");
|
||||||
if (pledge("stdio rpath wpath cpath flock fattr unix getpw sendfd "
|
if (pledge("stdio rpath wpath cpath flock fattr unix getpw sendfd "
|
||||||
"recvfd proc exec tty ps", NULL) != 0)
|
"recvfd proc exec tty ps", NULL) != 0)
|
||||||
err(1, "pledge");
|
err(1, "pledge");
|
||||||
|
|||||||
196
tmux.h
196
tmux.h
@@ -45,6 +45,7 @@ struct client;
|
|||||||
struct cmdq_item;
|
struct cmdq_item;
|
||||||
struct cmdq_list;
|
struct cmdq_list;
|
||||||
struct environ;
|
struct environ;
|
||||||
|
struct format_job_tree;
|
||||||
struct input_ctx;
|
struct input_ctx;
|
||||||
struct mode_key_cmdstr;
|
struct mode_key_cmdstr;
|
||||||
struct mouse_event;
|
struct mouse_event;
|
||||||
@@ -94,9 +95,10 @@ struct tmuxproc;
|
|||||||
#define KEYC_ESCAPE 0x200000000000ULL
|
#define KEYC_ESCAPE 0x200000000000ULL
|
||||||
#define KEYC_CTRL 0x400000000000ULL
|
#define KEYC_CTRL 0x400000000000ULL
|
||||||
#define KEYC_SHIFT 0x800000000000ULL
|
#define KEYC_SHIFT 0x800000000000ULL
|
||||||
|
#define KEYC_XTERM 0x1000000000000ULL
|
||||||
|
|
||||||
/* Mask to obtain key w/o modifiers. */
|
/* Mask to obtain key w/o modifiers. */
|
||||||
#define KEYC_MASK_MOD (KEYC_ESCAPE|KEYC_CTRL|KEYC_SHIFT)
|
#define KEYC_MASK_MOD (KEYC_ESCAPE|KEYC_CTRL|KEYC_SHIFT|KEYC_XTERM)
|
||||||
#define KEYC_MASK_KEY (~KEYC_MASK_MOD)
|
#define KEYC_MASK_KEY (~KEYC_MASK_MOD)
|
||||||
|
|
||||||
/* Is this a mouse key? */
|
/* Is this a mouse key? */
|
||||||
@@ -592,6 +594,10 @@ struct hook {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Scheduled job. */
|
/* Scheduled job. */
|
||||||
|
struct job;
|
||||||
|
typedef void (*job_update_cb) (struct job *);
|
||||||
|
typedef void (*job_complete_cb) (struct job *);
|
||||||
|
typedef void (*job_free_cb) (void *);
|
||||||
struct job {
|
struct job {
|
||||||
enum {
|
enum {
|
||||||
JOB_RUNNING,
|
JOB_RUNNING,
|
||||||
@@ -599,18 +605,19 @@ struct job {
|
|||||||
JOB_CLOSED
|
JOB_CLOSED
|
||||||
} state;
|
} state;
|
||||||
|
|
||||||
char *cmd;
|
char *cmd;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
int fd;
|
int fd;
|
||||||
struct bufferevent *event;
|
struct bufferevent *event;
|
||||||
|
|
||||||
void (*callbackfn)(struct job *);
|
job_update_cb updatecb;
|
||||||
void (*freefn)(void *);
|
job_complete_cb completecb;
|
||||||
void *data;
|
job_free_cb freecb;
|
||||||
|
void *data;
|
||||||
|
|
||||||
LIST_ENTRY(job) lentry;
|
LIST_ENTRY(job) entry;
|
||||||
};
|
};
|
||||||
LIST_HEAD(joblist, job);
|
LIST_HEAD(joblist, job);
|
||||||
|
|
||||||
@@ -686,15 +693,18 @@ struct screen_write_ctx {
|
|||||||
* right function to handle input and output.
|
* right function to handle input and output.
|
||||||
*/
|
*/
|
||||||
struct window_mode {
|
struct window_mode {
|
||||||
struct screen *(*init)(struct window_pane *);
|
const char *name;
|
||||||
void (*free)(struct window_pane *);
|
|
||||||
void (*resize)(struct window_pane *, u_int, u_int);
|
|
||||||
void (*key)(struct window_pane *, struct client *, struct session *,
|
|
||||||
key_code, struct mouse_event *);
|
|
||||||
|
|
||||||
const char *(*key_table)(struct window_pane *);
|
struct screen *(*init)(struct window_pane *);
|
||||||
void (*command)(struct window_pane *, struct client *,
|
void (*free)(struct window_pane *);
|
||||||
struct session *, struct args *, struct mouse_event *);
|
void (*resize)(struct window_pane *, u_int, u_int);
|
||||||
|
void (*key)(struct window_pane *, struct client *,
|
||||||
|
struct session *, key_code, struct mouse_event *);
|
||||||
|
|
||||||
|
const char *(*key_table)(struct window_pane *);
|
||||||
|
void (*command)(struct window_pane *, struct client *,
|
||||||
|
struct session *, struct args *,
|
||||||
|
struct mouse_event *);
|
||||||
};
|
};
|
||||||
#define WINDOW_MODE_TIMEOUT 180
|
#define WINDOW_MODE_TIMEOUT 180
|
||||||
|
|
||||||
@@ -1047,7 +1057,8 @@ struct tty {
|
|||||||
struct evbuffer *in;
|
struct evbuffer *in;
|
||||||
struct event event_out;
|
struct event event_out;
|
||||||
struct evbuffer *out;
|
struct evbuffer *out;
|
||||||
size_t written;
|
struct event timer;
|
||||||
|
size_t discarded;
|
||||||
|
|
||||||
struct termios tio;
|
struct termios tio;
|
||||||
|
|
||||||
@@ -1063,6 +1074,7 @@ struct tty {
|
|||||||
#define TTY_STARTED 0x10
|
#define TTY_STARTED 0x10
|
||||||
#define TTY_OPENED 0x20
|
#define TTY_OPENED 0x20
|
||||||
#define TTY_FOCUS 0x40
|
#define TTY_FOCUS 0x40
|
||||||
|
#define TTY_BLOCK 0x80
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
struct tty_term *term;
|
struct tty_term *term;
|
||||||
@@ -1089,13 +1101,14 @@ struct tty {
|
|||||||
struct tty_key *key_tree;
|
struct tty_key *key_tree;
|
||||||
};
|
};
|
||||||
#define TTY_TYPES \
|
#define TTY_TYPES \
|
||||||
{ "VT100", "VT101", "VT102", "VT220", "VT320", "VT420", "UNKNOWN" }
|
{ "VT100", "VT101", "VT102", "VT220", "VT320", "VT420", "Unknown" }
|
||||||
|
|
||||||
/* TTY command context. */
|
/* TTY command context. */
|
||||||
struct tty_ctx {
|
struct tty_ctx {
|
||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
|
|
||||||
const struct grid_cell *cell;
|
const struct grid_cell *cell;
|
||||||
|
int wrapped;
|
||||||
|
|
||||||
u_int num;
|
u_int num;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
@@ -1142,7 +1155,6 @@ enum cmd_find_type {
|
|||||||
CMD_FIND_SESSION,
|
CMD_FIND_SESSION,
|
||||||
};
|
};
|
||||||
struct cmd_find_state {
|
struct cmd_find_state {
|
||||||
struct cmdq_item *item;
|
|
||||||
int flags;
|
int flags;
|
||||||
struct cmd_find_state *current;
|
struct cmd_find_state *current;
|
||||||
|
|
||||||
@@ -1160,13 +1172,7 @@ struct cmd_find_state {
|
|||||||
#define CMD_FIND_DEFAULT_MARKED 0x8
|
#define CMD_FIND_DEFAULT_MARKED 0x8
|
||||||
#define CMD_FIND_EXACT_SESSION 0x10
|
#define CMD_FIND_EXACT_SESSION 0x10
|
||||||
#define CMD_FIND_EXACT_WINDOW 0x20
|
#define CMD_FIND_EXACT_WINDOW 0x20
|
||||||
|
#define CMD_FIND_CANFAIL 0x40
|
||||||
/* Context for command being executed. */
|
|
||||||
struct cmd_state {
|
|
||||||
struct client *c;
|
|
||||||
struct cmd_find_state tflag;
|
|
||||||
struct cmd_find_state sflag;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Command and list of commands. */
|
/* Command and list of commands. */
|
||||||
struct cmd {
|
struct cmd {
|
||||||
@@ -1201,6 +1207,19 @@ enum cmdq_type {
|
|||||||
CMDQ_CALLBACK,
|
CMDQ_CALLBACK,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Command queue item shared state. */
|
||||||
|
struct cmdq_shared {
|
||||||
|
int references;
|
||||||
|
|
||||||
|
int flags;
|
||||||
|
#define CMDQ_SHARED_REPEAT 0x1
|
||||||
|
|
||||||
|
struct format_tree *formats;
|
||||||
|
|
||||||
|
struct mouse_event mouse;
|
||||||
|
struct cmd_find_state current;
|
||||||
|
};
|
||||||
|
|
||||||
/* Command queue item. */
|
/* Command queue item. */
|
||||||
typedef enum cmd_retval (*cmdq_cb) (struct cmdq_item *, void *);
|
typedef enum cmd_retval (*cmdq_cb) (struct cmdq_item *, void *);
|
||||||
struct cmdq_item {
|
struct cmdq_item {
|
||||||
@@ -1216,51 +1235,30 @@ struct cmdq_item {
|
|||||||
u_int number;
|
u_int number;
|
||||||
time_t time;
|
time_t time;
|
||||||
|
|
||||||
struct format_tree *formats;
|
|
||||||
|
|
||||||
int flags;
|
int flags;
|
||||||
#define CMDQ_FIRED 0x1
|
#define CMDQ_FIRED 0x1
|
||||||
#define CMDQ_WAITING 0x2
|
#define CMDQ_WAITING 0x2
|
||||||
#define CMDQ_NOHOOKS 0x4
|
#define CMDQ_NOHOOKS 0x4
|
||||||
|
|
||||||
|
struct cmdq_shared *shared;
|
||||||
|
struct cmd_find_state source;
|
||||||
|
struct cmd_find_state target;
|
||||||
|
|
||||||
struct cmd_list *cmdlist;
|
struct cmd_list *cmdlist;
|
||||||
struct cmd *cmd;
|
struct cmd *cmd;
|
||||||
int repeat;
|
|
||||||
|
|
||||||
cmdq_cb cb;
|
cmdq_cb cb;
|
||||||
void *data;
|
void *data;
|
||||||
|
|
||||||
struct cmd_find_state current;
|
|
||||||
struct cmd_state state;
|
|
||||||
|
|
||||||
struct mouse_event mouse;
|
|
||||||
|
|
||||||
TAILQ_ENTRY(cmdq_item) entry;
|
TAILQ_ENTRY(cmdq_item) entry;
|
||||||
};
|
};
|
||||||
TAILQ_HEAD(cmdq_list, cmdq_item);
|
TAILQ_HEAD(cmdq_list, cmdq_item);
|
||||||
|
|
||||||
/* Command -c, -t or -s flags. */
|
/* Command definition flag. */
|
||||||
enum cmd_entry_flag {
|
struct cmd_entry_flag {
|
||||||
CMD_NONE,
|
char flag;
|
||||||
|
enum cmd_find_type type;
|
||||||
CMD_CLIENT,
|
int flags;
|
||||||
CMD_CLIENT_CANFAIL,
|
|
||||||
|
|
||||||
CMD_SESSION,
|
|
||||||
CMD_SESSION_CANFAIL,
|
|
||||||
CMD_SESSION_PREFERUNATTACHED,
|
|
||||||
CMD_SESSION_WITHPANE, /* implies PREFERUNATTACHED */
|
|
||||||
|
|
||||||
CMD_WINDOW,
|
|
||||||
CMD_WINDOW_CANFAIL,
|
|
||||||
CMD_WINDOW_MARKED,
|
|
||||||
CMD_WINDOW_INDEX,
|
|
||||||
|
|
||||||
CMD_PANE,
|
|
||||||
CMD_PANE_CANFAIL,
|
|
||||||
CMD_PANE_MARKED,
|
|
||||||
|
|
||||||
CMD_MOVEW_R,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Command definition. */
|
/* Command definition. */
|
||||||
@@ -1275,16 +1273,15 @@ struct cmd_entry {
|
|||||||
} args;
|
} args;
|
||||||
const char *usage;
|
const char *usage;
|
||||||
|
|
||||||
enum cmd_entry_flag tflag;
|
struct cmd_entry_flag source;
|
||||||
enum cmd_entry_flag sflag;
|
struct cmd_entry_flag target;
|
||||||
enum cmd_entry_flag cflag;
|
|
||||||
|
|
||||||
#define CMD_STARTSERVER 0x1
|
#define CMD_STARTSERVER 0x1
|
||||||
#define CMD_READONLY 0x2
|
#define CMD_READONLY 0x2
|
||||||
#define CMD_AFTERHOOK 0x4
|
#define CMD_AFTERHOOK 0x4
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
enum cmd_retval (*exec)(struct cmd *, struct cmdq_item *);
|
enum cmd_retval (*exec)(struct cmd *, struct cmdq_item *);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Client connection. */
|
/* Client connection. */
|
||||||
@@ -1302,6 +1299,7 @@ struct client {
|
|||||||
struct timeval activity_time;
|
struct timeval activity_time;
|
||||||
|
|
||||||
struct environ *environ;
|
struct environ *environ;
|
||||||
|
struct format_job_tree *jobs;
|
||||||
|
|
||||||
char *title;
|
char *title;
|
||||||
const char *cwd;
|
const char *cwd;
|
||||||
@@ -1310,6 +1308,10 @@ struct client {
|
|||||||
char *ttyname;
|
char *ttyname;
|
||||||
struct tty tty;
|
struct tty tty;
|
||||||
|
|
||||||
|
size_t written;
|
||||||
|
size_t discarded;
|
||||||
|
size_t redraw;
|
||||||
|
|
||||||
void (*stdin_callback)(struct client *, int, void *);
|
void (*stdin_callback)(struct client *, int, void *);
|
||||||
void *stdin_callback_data;
|
void *stdin_callback_data;
|
||||||
struct evbuffer *stdin_data;
|
struct evbuffer *stdin_data;
|
||||||
@@ -1337,7 +1339,7 @@ struct client {
|
|||||||
#define CLIENT_DEAD 0x200
|
#define CLIENT_DEAD 0x200
|
||||||
#define CLIENT_BORDERS 0x400
|
#define CLIENT_BORDERS 0x400
|
||||||
#define CLIENT_READONLY 0x800
|
#define CLIENT_READONLY 0x800
|
||||||
/* 0x1000 unused */
|
#define CLIENT_DETACHING 0x1000
|
||||||
#define CLIENT_CONTROL 0x2000
|
#define CLIENT_CONTROL 0x2000
|
||||||
#define CLIENT_CONTROLCONTROL 0x4000
|
#define CLIENT_CONTROLCONTROL 0x4000
|
||||||
#define CLIENT_FOCUSED 0x8000
|
#define CLIENT_FOCUSED 0x8000
|
||||||
@@ -1388,7 +1390,9 @@ TAILQ_HEAD(clients, client);
|
|||||||
struct key_binding {
|
struct key_binding {
|
||||||
key_code key;
|
key_code key;
|
||||||
struct cmd_list *cmdlist;
|
struct cmd_list *cmdlist;
|
||||||
int can_repeat;
|
|
||||||
|
int flags;
|
||||||
|
#define KEY_BINDING_REPEAT 0x1
|
||||||
|
|
||||||
RB_ENTRY(key_binding) entry;
|
RB_ENTRY(key_binding) entry;
|
||||||
};
|
};
|
||||||
@@ -1478,7 +1482,6 @@ void proc_kill_peer(struct tmuxpeer *);
|
|||||||
|
|
||||||
/* cfg.c */
|
/* cfg.c */
|
||||||
extern int cfg_finished;
|
extern int cfg_finished;
|
||||||
extern struct client *cfg_client;
|
|
||||||
void start_cfg(void);
|
void start_cfg(void);
|
||||||
int load_cfg(const char *, struct client *, struct cmdq_item *, int);
|
int load_cfg(const char *, struct client *, struct cmdq_item *, int);
|
||||||
void set_cfg_file(const char *);
|
void set_cfg_file(const char *);
|
||||||
@@ -1509,7 +1512,8 @@ char *paste_make_sample(struct paste_buffer *);
|
|||||||
#define FORMAT_PANE 0x80000000U
|
#define FORMAT_PANE 0x80000000U
|
||||||
#define FORMAT_WINDOW 0x40000000U
|
#define FORMAT_WINDOW 0x40000000U
|
||||||
struct format_tree;
|
struct format_tree;
|
||||||
struct format_tree *format_create(struct cmdq_item *, int, int);
|
struct format_tree *format_create(struct client *, struct cmdq_item *, int,
|
||||||
|
int);
|
||||||
void format_free(struct format_tree *);
|
void format_free(struct format_tree *);
|
||||||
void printflike(3, 4) format_add(struct format_tree *, const char *,
|
void printflike(3, 4) format_add(struct format_tree *, const char *,
|
||||||
const char *, ...);
|
const char *, ...);
|
||||||
@@ -1525,6 +1529,7 @@ void format_defaults_pane(struct format_tree *,
|
|||||||
struct window_pane *);
|
struct window_pane *);
|
||||||
void format_defaults_paste_buffer(struct format_tree *,
|
void format_defaults_paste_buffer(struct format_tree *,
|
||||||
struct paste_buffer *);
|
struct paste_buffer *);
|
||||||
|
void format_lost_client(struct client *);
|
||||||
|
|
||||||
/* hooks.c */
|
/* hooks.c */
|
||||||
struct hook;
|
struct hook;
|
||||||
@@ -1546,7 +1551,7 @@ void printflike(4, 5) hooks_insert(struct hooks *, struct cmdq_item *,
|
|||||||
void notify_input(struct window_pane *, struct evbuffer *);
|
void notify_input(struct window_pane *, struct evbuffer *);
|
||||||
void notify_client(const char *, struct client *);
|
void notify_client(const char *, struct client *);
|
||||||
void notify_session(const char *, struct session *);
|
void notify_session(const char *, struct session *);
|
||||||
void notify_winlink(const char *, struct session *, struct winlink *);
|
void notify_winlink(const char *, struct winlink *);
|
||||||
void notify_session_window(const char *, struct session *, struct window *);
|
void notify_session_window(const char *, struct session *, struct window *);
|
||||||
void notify_window(const char *, struct window *);
|
void notify_window(const char *, struct window *);
|
||||||
void notify_pane(const char *, struct window_pane *);
|
void notify_pane(const char *, struct window_pane *);
|
||||||
@@ -1600,10 +1605,10 @@ extern const struct options_table_entry options_table[];
|
|||||||
|
|
||||||
/* job.c */
|
/* job.c */
|
||||||
extern struct joblist all_jobs;
|
extern struct joblist all_jobs;
|
||||||
struct job *job_run(const char *, struct session *, const char *,
|
struct job *job_run(const char *, struct session *, const char *,
|
||||||
void (*)(struct job *), void (*)(void *), void *);
|
job_update_cb, job_complete_cb, job_free_cb, void *);
|
||||||
void job_free(struct job *);
|
void job_free(struct job *);
|
||||||
void job_died(struct job *, int);
|
void job_died(struct job *, int);
|
||||||
|
|
||||||
/* environ.c */
|
/* environ.c */
|
||||||
struct environ *environ_create(void);
|
struct environ *environ_create(void);
|
||||||
@@ -1620,7 +1625,7 @@ void environ_unset(struct environ *, const char *);
|
|||||||
void environ_update(struct options *, struct environ *, struct environ *);
|
void environ_update(struct options *, struct environ *, struct environ *);
|
||||||
void environ_push(struct environ *);
|
void environ_push(struct environ *);
|
||||||
void environ_log(struct environ *, const char *);
|
void environ_log(struct environ *, const char *);
|
||||||
struct environ *environ_for_session(struct session *);
|
struct environ *environ_for_session(struct session *, int);
|
||||||
|
|
||||||
/* tty.c */
|
/* tty.c */
|
||||||
void tty_create_log(void);
|
void tty_create_log(void);
|
||||||
@@ -1714,28 +1719,30 @@ long long args_strtonum(struct args *, u_char, long long, long long,
|
|||||||
char **);
|
char **);
|
||||||
|
|
||||||
/* cmd-find.c */
|
/* cmd-find.c */
|
||||||
int cmd_find_current(struct cmd_find_state *, struct cmdq_item *,
|
int cmd_find_target(struct cmd_find_state *, struct cmdq_item *,
|
||||||
int);
|
const char *, enum cmd_find_type, int);
|
||||||
int cmd_find_target(struct cmd_find_state *,
|
|
||||||
struct cmd_find_state *, struct cmdq_item *, const char *,
|
|
||||||
enum cmd_find_type, int);
|
|
||||||
struct client *cmd_find_client(struct cmdq_item *, const char *, int);
|
struct client *cmd_find_client(struct cmdq_item *, const char *, int);
|
||||||
void cmd_find_clear_state(struct cmd_find_state *,
|
void cmd_find_clear_state(struct cmd_find_state *, int);
|
||||||
struct cmdq_item *, int);
|
|
||||||
int cmd_find_empty_state(struct cmd_find_state *);
|
int cmd_find_empty_state(struct cmd_find_state *);
|
||||||
int cmd_find_valid_state(struct cmd_find_state *);
|
int cmd_find_valid_state(struct cmd_find_state *);
|
||||||
void cmd_find_copy_state(struct cmd_find_state *,
|
void cmd_find_copy_state(struct cmd_find_state *,
|
||||||
struct cmd_find_state *);
|
struct cmd_find_state *);
|
||||||
void cmd_find_log_state(const char *, struct cmd_find_state *);
|
void cmd_find_log_state(const char *, struct cmd_find_state *);
|
||||||
int cmd_find_from_session(struct cmd_find_state *,
|
void cmd_find_from_session(struct cmd_find_state *,
|
||||||
struct session *);
|
struct session *);
|
||||||
int cmd_find_from_winlink(struct cmd_find_state *,
|
void cmd_find_from_winlink(struct cmd_find_state *,
|
||||||
struct session *, struct winlink *);
|
struct winlink *);
|
||||||
int cmd_find_from_session_window(struct cmd_find_state *,
|
int cmd_find_from_session_window(struct cmd_find_state *,
|
||||||
struct session *, struct window *);
|
struct session *, struct window *);
|
||||||
int cmd_find_from_window(struct cmd_find_state *, struct window *);
|
int cmd_find_from_window(struct cmd_find_state *, struct window *);
|
||||||
|
void cmd_find_from_winlink_pane(struct cmd_find_state *,
|
||||||
|
struct winlink *, struct window_pane *);
|
||||||
int cmd_find_from_pane(struct cmd_find_state *,
|
int cmd_find_from_pane(struct cmd_find_state *,
|
||||||
struct window_pane *);
|
struct window_pane *);
|
||||||
|
int cmd_find_from_client(struct cmd_find_state *, struct client *);
|
||||||
|
int cmd_find_from_mouse(struct cmd_find_state *,
|
||||||
|
struct mouse_event *);
|
||||||
|
int cmd_find_from_nothing(struct cmd_find_state *);
|
||||||
|
|
||||||
/* cmd.c */
|
/* cmd.c */
|
||||||
int cmd_pack_argv(int, char **, char *, size_t);
|
int cmd_pack_argv(int, char **, char *, size_t);
|
||||||
@@ -1744,7 +1751,6 @@ char **cmd_copy_argv(int, char **);
|
|||||||
void cmd_free_argv(int, char **);
|
void cmd_free_argv(int, char **);
|
||||||
char *cmd_stringify_argv(int, char **);
|
char *cmd_stringify_argv(int, char **);
|
||||||
struct cmd *cmd_parse(int, char **, const char *, u_int, char **);
|
struct cmd *cmd_parse(int, char **, const char *, u_int, char **);
|
||||||
int cmd_prepare_state(struct cmd *, struct cmdq_item *);
|
|
||||||
char *cmd_print(struct cmd *);
|
char *cmd_print(struct cmd *);
|
||||||
int cmd_mouse_at(struct window_pane *, struct mouse_event *,
|
int cmd_mouse_at(struct window_pane *, struct mouse_event *,
|
||||||
u_int *, u_int *, int);
|
u_int *, u_int *, int);
|
||||||
@@ -1755,8 +1761,8 @@ char *cmd_template_replace(const char *, const char *, int);
|
|||||||
extern const struct cmd_entry *cmd_table[];
|
extern const struct cmd_entry *cmd_table[];
|
||||||
|
|
||||||
/* cmd-attach-session.c */
|
/* cmd-attach-session.c */
|
||||||
enum cmd_retval cmd_attach_session(struct cmdq_item *, int, int, const char *,
|
enum cmd_retval cmd_attach_session(struct cmdq_item *, const char *, int, int,
|
||||||
int);
|
const char *, int);
|
||||||
|
|
||||||
/* cmd-list.c */
|
/* cmd-list.c */
|
||||||
struct cmd_list *cmd_list_parse(int, char **, const char *, u_int, char **);
|
struct cmd_list *cmd_list_parse(int, char **, const char *, u_int, char **);
|
||||||
@@ -1830,13 +1836,13 @@ void server_client_set_identify(struct client *);
|
|||||||
void server_client_clear_identify(struct client *, struct window_pane *);
|
void server_client_clear_identify(struct client *, struct window_pane *);
|
||||||
void server_client_set_key_table(struct client *, const char *);
|
void server_client_set_key_table(struct client *, const char *);
|
||||||
const char *server_client_get_key_table(struct client *);
|
const char *server_client_get_key_table(struct client *);
|
||||||
int server_client_is_default_key_table(struct client *);
|
|
||||||
int server_client_check_nested(struct client *);
|
int server_client_check_nested(struct client *);
|
||||||
void server_client_handle_key(struct client *, key_code);
|
void server_client_handle_key(struct client *, key_code);
|
||||||
void server_client_create(int);
|
void server_client_create(int);
|
||||||
int server_client_open(struct client *, char **);
|
int server_client_open(struct client *, char **);
|
||||||
void server_client_unref(struct client *);
|
void server_client_unref(struct client *);
|
||||||
void server_client_lost(struct client *);
|
void server_client_lost(struct client *);
|
||||||
|
void server_client_suspend(struct client *);
|
||||||
void server_client_detach(struct client *, enum msgtype);
|
void server_client_detach(struct client *, enum msgtype);
|
||||||
void server_client_exec(struct client *, const char *);
|
void server_client_exec(struct client *, const char *);
|
||||||
void server_client_loop(void);
|
void server_client_loop(void);
|
||||||
@@ -1993,7 +1999,7 @@ void screen_write_cursorleft(struct screen_write_ctx *, u_int);
|
|||||||
void screen_write_alignmenttest(struct screen_write_ctx *);
|
void screen_write_alignmenttest(struct screen_write_ctx *);
|
||||||
void screen_write_insertcharacter(struct screen_write_ctx *, u_int, u_int);
|
void screen_write_insertcharacter(struct screen_write_ctx *, u_int, u_int);
|
||||||
void screen_write_deletecharacter(struct screen_write_ctx *, u_int, u_int);
|
void screen_write_deletecharacter(struct screen_write_ctx *, u_int, u_int);
|
||||||
void screen_write_clearcharacter(struct screen_write_ctx *, u_int);
|
void screen_write_clearcharacter(struct screen_write_ctx *, u_int, u_int);
|
||||||
void screen_write_insertline(struct screen_write_ctx *, u_int, u_int);
|
void screen_write_insertline(struct screen_write_ctx *, u_int, u_int);
|
||||||
void screen_write_deleteline(struct screen_write_ctx *, u_int, u_int);
|
void screen_write_deleteline(struct screen_write_ctx *, u_int, u_int);
|
||||||
void screen_write_clearline(struct screen_write_ctx *, u_int);
|
void screen_write_clearline(struct screen_write_ctx *, u_int);
|
||||||
@@ -2113,13 +2119,14 @@ int window_pane_outside(struct window_pane *);
|
|||||||
int window_pane_visible(struct window_pane *);
|
int window_pane_visible(struct window_pane *);
|
||||||
char *window_pane_search(struct window_pane *, const char *,
|
char *window_pane_search(struct window_pane *, const char *,
|
||||||
u_int *);
|
u_int *);
|
||||||
char *window_printable_flags(struct session *, struct winlink *);
|
const char *window_printable_flags(struct winlink *);
|
||||||
struct window_pane *window_pane_find_up(struct window_pane *);
|
struct window_pane *window_pane_find_up(struct window_pane *);
|
||||||
struct window_pane *window_pane_find_down(struct window_pane *);
|
struct window_pane *window_pane_find_down(struct window_pane *);
|
||||||
struct window_pane *window_pane_find_left(struct window_pane *);
|
struct window_pane *window_pane_find_left(struct window_pane *);
|
||||||
struct window_pane *window_pane_find_right(struct window_pane *);
|
struct window_pane *window_pane_find_right(struct window_pane *);
|
||||||
void window_set_name(struct window *, const char *);
|
void window_set_name(struct window *, const char *);
|
||||||
void window_remove_ref(struct window *);
|
void window_add_ref(struct window *, const char *);
|
||||||
|
void window_remove_ref(struct window *, const char *);
|
||||||
void winlink_clear_flags(struct winlink *);
|
void winlink_clear_flags(struct winlink *);
|
||||||
int winlink_shuffle_up(struct session *, struct winlink *);
|
int winlink_shuffle_up(struct session *, struct winlink *);
|
||||||
|
|
||||||
@@ -2173,6 +2180,7 @@ void window_copy_vadd(struct window_pane *, const char *, va_list);
|
|||||||
void window_copy_pageup(struct window_pane *, int);
|
void window_copy_pageup(struct window_pane *, int);
|
||||||
void window_copy_start_drag(struct client *, struct mouse_event *);
|
void window_copy_start_drag(struct client *, struct mouse_event *);
|
||||||
int window_copy_scroll_position(struct window_pane *);
|
int window_copy_scroll_position(struct window_pane *);
|
||||||
|
const char *window_copy_search_string(struct window_pane *);
|
||||||
|
|
||||||
/* window-choose.c */
|
/* window-choose.c */
|
||||||
extern const struct window_mode window_choose_mode;
|
extern const struct window_mode window_choose_mode;
|
||||||
@@ -2209,7 +2217,9 @@ void control_write_buffer(struct client *, struct evbuffer *);
|
|||||||
/* control-notify.c */
|
/* control-notify.c */
|
||||||
void control_notify_input(struct client *, struct window_pane *,
|
void control_notify_input(struct client *, struct window_pane *,
|
||||||
struct evbuffer *);
|
struct evbuffer *);
|
||||||
|
void control_notify_pane_mode_changed(int);
|
||||||
void control_notify_window_layout_changed(struct window *);
|
void control_notify_window_layout_changed(struct window *);
|
||||||
|
void control_notify_window_pane_changed(struct window *);
|
||||||
void control_notify_window_unlinked(struct session *, struct window *);
|
void control_notify_window_unlinked(struct session *, struct window *);
|
||||||
void control_notify_window_linked(struct session *, struct window *);
|
void control_notify_window_linked(struct session *, struct window *);
|
||||||
void control_notify_window_renamed(struct window *);
|
void control_notify_window_renamed(struct window *);
|
||||||
@@ -2217,6 +2227,7 @@ void control_notify_client_session_changed(struct client *);
|
|||||||
void control_notify_session_renamed(struct session *);
|
void control_notify_session_renamed(struct session *);
|
||||||
void control_notify_session_created(struct session *);
|
void control_notify_session_created(struct session *);
|
||||||
void control_notify_session_closed(struct session *);
|
void control_notify_session_closed(struct session *);
|
||||||
|
void control_notify_session_window_changed(struct session *);
|
||||||
|
|
||||||
/* session.c */
|
/* session.c */
|
||||||
extern struct sessions sessions;
|
extern struct sessions sessions;
|
||||||
@@ -2233,7 +2244,8 @@ struct session *session_create(const char *, const char *, int, char **,
|
|||||||
const char *, const char *, struct environ *,
|
const char *, const char *, struct environ *,
|
||||||
struct termios *, int, u_int, u_int, char **);
|
struct termios *, int, u_int, u_int, char **);
|
||||||
void session_destroy(struct session *);
|
void session_destroy(struct session *);
|
||||||
void session_unref(struct session *);
|
void session_add_ref(struct session *, const char *);
|
||||||
|
void session_remove_ref(struct session *, const char *);
|
||||||
int session_check_name(const char *);
|
int session_check_name(const char *);
|
||||||
void session_update_activity(struct session *, struct timeval *);
|
void session_update_activity(struct session *, struct timeval *);
|
||||||
struct session *session_next_session(struct session *);
|
struct session *session_next_session(struct session *);
|
||||||
@@ -2302,8 +2314,4 @@ void style_apply_update(struct grid_cell *, struct options *,
|
|||||||
int style_equal(const struct grid_cell *,
|
int style_equal(const struct grid_cell *,
|
||||||
const struct grid_cell *);
|
const struct grid_cell *);
|
||||||
|
|
||||||
/* pty.c */
|
|
||||||
int pty_open(int *);
|
|
||||||
pid_t pty_fork(int, int *, char *, size_t, struct winsize *);
|
|
||||||
|
|
||||||
#endif /* TMUX_H */
|
#endif /* TMUX_H */
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user