582 Commits
1.2 ... 1.6

Author SHA1 Message Date
Tiago Cunha
88c831af6e Tag 1.6 release. 2012-01-23 12:59:12 +00:00
Tiago Cunha
e254aeb9f9 Major changes since the previous version. 2012-01-23 12:41:36 +00:00
Tiago Cunha
1d4c54717c Add notes about some potential configuration file breaking in the 1.6 release. 2012-01-23 12:38:05 +00:00
Tiago Cunha
30b816f101 Done. 2012-01-23 12:35:55 +00:00
Tiago Cunha
9803aee98e Releases don't have debugging enabled. 2012-01-23 12:34:47 +00:00
Tiago Cunha
a34a72d2d9 Sync OpenBSD patchset 1011:
Remove unused backoff code that doesn't do any good.
2012-01-23 12:24:00 +00:00
Tiago Cunha
4d80980e50 Sync OpenBSD patchset 1010:
Show pane size in top right of display panes mode.
2012-01-23 12:23:27 +00:00
Tiago Cunha
85152ef35c Expand the Id keyword. 2012-01-22 23:41:34 +00:00
Tiago Cunha
ebce251183 Sync OpenBSD patchset 1009:
it's -> its.
2012-01-21 21:40:33 +00:00
Tiago Cunha
a3c1b730c9 Sync OpenBSD patchset 1008:
Use RB trees not SPLAY.
2012-01-21 19:38:26 +00:00
Tiago Cunha
a7b0b30bdd Sync OpenBSD patchset 1007:
Drop the ability to have a list of keys in the prefix in favour of two
separate options, prefix and prefix2. This simplifies the code and gets
rid the data options type which was only used for this one option.

Also add a -2 flag to send-prefix to send the secondary prefix key,
fixing a cause of minor irritation.

People who want three prefix keys are out of luck :-).
2012-01-21 19:36:40 +00:00
Tiago Cunha
d4c2a935f2 Sync OpenBSD patchset 1006:
Add strings to allow the aixterm bright colours to be used when
configuring colours, requested by Elliott Cable a few months ago.
2012-01-21 19:33:45 +00:00
Tiago Cunha
cc967ffeb9 Sync OpenBSD patchset 1005:
One day I will actually fix ALL the warnings before I commit...
2012-01-21 19:32:36 +00:00
Tiago Cunha
4bea559037 Sync OpenBSD patchset 1004:
Add a -R flag to send-keys to reset the terminal. Written ages ago and
Suggested by someone, I forget who.
2012-01-21 19:31:59 +00:00
Tiago Cunha
674de910ca Sync OpenBSD patchset 1003:
Only hide flags on the current window when the session is attached, from
Roland Walker.
2012-01-21 19:30:07 +00:00
Tiago Cunha
5434a2759a Sync OpenBSD patchset 1002:
Add some const and fix a warning.
2012-01-20 21:21:32 +00:00
Tiago Cunha
b7551c9193 Sync OpenBSD patchset 1001:
Add some trivial additional status line attributes from jwcxz at users
dot sourceforge dot net.
2012-01-20 21:20:35 +00:00
Tiago Cunha
d4312281da Sync OpenBSD patchset 1000:
Remove trailing spaces.
2012-01-20 21:19:20 +00:00
Tiago Cunha
d9eb34b28d Sync OpenBSD patchset 999:
Add an option to disable the window rename escape sequence, from Romain
Francoise.
2012-01-20 21:18:39 +00:00
Tiago Cunha
b79189958f Sync OpenBSD patchset 998:
Add space movement keys for vi mode in the status line from Ben Boeckel.
2012-01-20 21:17:18 +00:00
Tiago Cunha
ad5c4e719b Sync OpenBSD patchset 997:
Calculate last position correctly for UTF-8 wide characters, reported by
Matthias Lederhofer.
2012-01-20 21:16:07 +00:00
Nicholas Marriott
db7570daab Set IUTF8 in termios where supported, suggested by Egmont Koblinger. 2012-01-20 20:18:20 +00:00
Tiago Cunha
60069fe8fe Sync OpenBSD patchset 995:
Add a man page section on window names and pane titles, from Felix
Rosencrantz.
2012-01-03 18:36:40 +00:00
Tiago Cunha
d817f88fec Sync OpenBSD patchset 995:
Show how to set default-path to revert to tmux's old behaviour of opening
new windows in the current working directory at the time tmux was started,
it's not obvious. naddy@ agrees this is a useful inclusion.
2012-01-03 18:35:54 +00:00
Tiago Cunha
90b331ea46 Sync OpenBSD patchset 994:
Add CNL and CPL escape sequences.
2011-12-30 14:21:40 +00:00
Tiago Cunha
e2d59a6c17 Sync OpenBSD patchset 993:
Allow $HOME as default-path in tmux.conf so the same config file can be used
on different machines regardless of where the user's home directory is.
ok nicm
2011-12-30 14:21:02 +00:00
Tiago Cunha
2ca1849350 Sync OpenBSD patchset 992:
Add \033[s and \033[u to save and restore cursor position.
2011-12-30 14:19:21 +00:00
Tiago Cunha
e210abf335 $Id$ not $OpenBSD$. 2011-12-30 14:18:27 +00:00
Tiago Cunha
f9b4095188 Sync OpenBSD patchset 991:
Extend history that can be captured to INT_MIN rather than
SHRT_MIN. From Chris Johnsen.
2011-12-30 14:16:44 +00:00
Tiago Cunha
d1f0138653 Sync OpenBSD patchset 990:
Reset flags on every loop or it is displayed too often, from Chris
Johnsen.
2011-12-30 14:15:40 +00:00
Tiago Cunha
9e7ec2e971 Sync OpenBSD patchset 989:
formatting errors, found using freebsd's "igor";
2011-12-25 23:36:27 +00:00
Tiago Cunha
3a9a24a7c0 Sync OpenBSD patchset 988:
Fix so that when mouse-select-pane and mouse-select-window are both
enabled, clicking on the status line does not change the current
pane. From Romain Francoise.
2011-12-25 23:33:30 +00:00
Nicholas Marriott
c1b9948525 Change the way the working directory for new processes is discovered. If
default-path isn't empty, it is used. Otherwise:

1) If tmux neww is run from the command line, the working directory of the
client is used.

2) Otherwise use some platform specific code to retrieve the current working
directory of the process in the active pane.

3) If that fails, the directory where the session was created is used.

Idea and support code, Linux, Solaris, FreeBSD bits by Romain Francoise,
OpenBSD bits by me.
2011-12-09 16:37:29 +00:00
Tiago Cunha
76862acf3e Sync OpenBSD patchset 986:
Support "jump to" like vi in copy mode using t and T keys. Also add x
and X for delete in edit mode.

From Ben Boeckel, thanks.
2011-12-06 18:50:26 +00:00
Tiago Cunha
f308663ad4 Sync OpenBSD patchset 985:
Log terminal overrides.
2011-12-06 18:48:45 +00:00
Tiago Cunha
876f46abb9 Sync OpenBSD patchset 984:
Add home and end keys for command prompt, from Matthias Lederhofer.
2011-12-06 18:48:02 +00:00
Tiago Cunha
620a87db25 Sync OpenBSD patchset 983:
Make M-f and M-b work the same at the command prompt as in copy mode,
pointed out by Romain Francoise.
2011-12-06 18:47:14 +00:00
Tiago Cunha
08014af243 New commands and options. From Ben Boeckel. 2011-11-25 14:31:11 +00:00
Tiago Cunha
774bffb3c6 Sync OpenBSD patchset 982:
Add word movement and editing command for command prompt editing, from
Ben Boeckel.
2011-11-25 13:34:20 +00:00
Tiago Cunha
9c920214e6 Sync OpenBSD patchset 981:
Move word-separators to be a session rather than window option, from Ben
Boeckel.
2011-11-25 13:33:04 +00:00
Tiago Cunha
5cc3d50289 Sync OpenBSD patchset 980:
Add a pane_index format string and use it, from Ben Boeckel.
2011-11-25 13:31:56 +00:00
Tiago Cunha
9ec457575d Sync OpenBSD patchset 979:
Make window_pane_index work the same as window_index, from Ben Boeckel.
2011-11-25 13:30:45 +00:00
Nicholas Marriott
398af28d2a +. 2011-11-15 23:12:28 +00:00
Tiago Cunha
8798079ab0 Typo. From Bastien Dejean. 2011-11-10 21:50:40 +00:00
Tiago Cunha
c26ec766cb Add command colour options. From Ben Boeckel. 2011-11-10 21:49:27 +00:00
Tiago Cunha
c3794d4303 Sync OpenBSD patchset 978:
Fix a trivial copy-and-paste error (sx->sy), from Chris Johnsen.
2011-11-10 21:41:37 +00:00
Tiago Cunha
4fbb296438 Sync OpenBSD patchset 977:
Missing bits for new keys and buffer indexes, from Tiago Cunha
2011-11-10 21:41:01 +00:00
Tiago Cunha
21128fea1e Sync OpenBSD patchset 976:
Option to change status line (message) background when using vi keys and
in command mode. From Ben Boeckel.
2011-11-10 21:40:17 +00:00
Nicholas Marriott
693c106a1d Add. 2011-11-09 12:00:11 +00:00
Tiago Cunha
046d8b096f Sync OpenBSD patchset 975:
minor formatting fix;
2011-10-31 13:56:55 +00:00
Tiago Cunha
0cbab892d5 Sync OpenBSD patchset 974:
Add screen*:XT to terminal-overrides for tmux-in-tmux, from Romain
Francoise.
2011-10-31 13:56:16 +00:00
Tiago Cunha
b44f78fe9f Sync OpenBSD patchset 973:
Missing -o on usage for pipe-pane, from Tiago Cunha.
2011-10-31 13:55:43 +00:00
Tiago Cunha
3f5ec24b5a Sync OpenBSD patchset 972:
Didn't really think the else behaviour through - requiring argv to
contain "else" is silly so just omit that, also some manpage
tweaks. From Tiago Cunha.
2011-10-31 13:55:10 +00:00
Tiago Cunha
d8d9c2af98 Sync OpenBSD patchset 971:
When copying, make repeat count indicate buffer to replace if used.
2011-10-31 13:54:28 +00:00
Nicholas Marriott
cf317412d9 Use pkg-config for libevent. 2011-10-27 23:00:45 +00:00
Nicholas Marriott
5213d9674b Add. 2011-10-27 22:43:02 +00:00
Tiago Cunha
0e45ca1718 Recognise special keys and binds with multiple modifiers. From Bastien Dejean. 2011-10-23 15:42:15 +00:00
Tiago Cunha
c1eeac86fe Sync OpenBSD patchset 970:
Alias NPage/PPage as PageDown/PgDn/PageUp/PgUp to reduce occasional
confusion.
2011-10-23 15:11:09 +00:00
Tiago Cunha
03ee7f7edf Sync OpenBSD patchset 969:
Support for \e[3J to clear the history. Also send the corresponding
terminfo code (E3) before locking.
2011-10-23 15:10:22 +00:00
Tiago Cunha
a8ca1340ad Sync OpenBSD patchset 968:
Try to resolve relative paths for loadb and saveb (first using client
working directory if any then default-path or session wd).
2011-10-23 15:08:58 +00:00
Tiago Cunha
7d169a3679 Sync OpenBSD patchset 967:
For initial session, use size of command client even if detached.
2011-10-23 15:05:20 +00:00
Tiago Cunha
98e500f598 Sync OpenBSD patchset 966:
Ignore LC_ALL and LC_CTYPE if they are empty as well as unset.
2011-10-23 15:04:30 +00:00
Tiago Cunha
1c1797e4f2 Sync OpenBSD patchset 965:
Add client formats, from Ben Boeckel.
2011-10-23 15:03:50 +00:00
Tiago Cunha
653d1e2fc8 Sync OpenBSD patchset 964:
Plug a memory leak and update some comments, from Tiago Cunha.
2011-10-23 15:02:20 +00:00
Tiago Cunha
9b48c77493 Sync OpenBSD patchset 963:
Add an else clause for if-shell, from "arno-" on SourceForge.
2011-10-23 15:00:41 +00:00
Nicholas Marriott
96146a8c6f Done. 2011-10-23 10:21:02 +00:00
Nicholas Marriott
7d53e2c946 Done! 2011-10-23 08:36:19 +00:00
Nicholas Marriott
213deb5c66 +. 2011-10-23 00:43:58 +00:00
Nicholas Marriott
69c1521895 +. 2011-10-23 00:31:35 +00:00
Nicholas Marriott
17e6dc4405 Add manpage, also spaces->tabs. 2011-10-10 20:17:17 +00:00
Nicholas Marriott
a7341715c1 Fix some warnings with newer autoconf, from Matt Curtis. 2011-10-06 12:14:22 +00:00
Tiago Cunha
521bf41d12 Sync OpenBSD patchset 962:
Add a few more formats for panes (tty, pid, start cmd/cwd).
2011-10-02 11:34:04 +00:00
Tiago Cunha
f0c3e9babe Sync OpenBSD patchset 961:
Add -S option to refresh-client to redraw status line, from Marco Beck.
2011-10-02 11:33:14 +00:00
Tiago Cunha
edd59d9e0f Sync OpenBSD patchset 960:
Reject $SHELL if it is not a full path.
2011-10-02 11:32:24 +00:00
Tiago Cunha
326c5bf1b4 Sync OpenBSD patchset 959:
Tweaks to the format parts, from Tiago Cunha.
2011-10-02 11:31:34 +00:00
Tiago Cunha
550906cb09 Sync OpenBSD patchset 958:
Fix typo: ) -> }.
2011-10-02 11:30:26 +00:00
Nicholas Marriott
175d82c95b Done. 2011-10-02 06:56:31 +00:00
Nicholas Marriott
3740f8f846 Add. 2011-10-02 06:44:16 +00:00
Nicholas Marriott
adfa5050d5 Add. 2011-10-02 06:33:32 +00:00
Nicholas Marriott
f62dcc1ea1 Separate dfly from fbsd as one or the other keeps becoming incompatible
;-). From Antonio Huete Jimenez
2011-09-29 08:43:01 +00:00
Nicholas Marriott
d6dc4c30f4 +. 2011-09-25 18:45:15 +00:00
Nicholas Marriott
d635d79042 The HAVE_DIRFD check should be for dirfd() not /proc/$$/fd. Doh. 2011-09-23 12:35:08 +00:00
Nicholas Marriott
b8ce435a54 +. 2011-09-23 12:34:31 +00:00
Tiago Cunha
6e0c097d9f Sync OpenBSD patchset 957:
Mark dead panes with some text saying they are dead, suggested by and
with help from Randy Stauner.
2011-09-21 16:35:13 +00:00
Tiago Cunha
d9807eeba1 Sync OpenBSD patchset 956:
Another memory leak from Tiago Cunha.
2011-09-21 16:34:34 +00:00
Tiago Cunha
cb752f9938 Sync OpenBSD patchset 955:
Plug memory leak, from Tiago Cunha.
2011-09-21 16:34:04 +00:00
Tiago Cunha
2e98603db9 Sync OpenBSD patchset 954:
tweak previous;
2011-09-21 16:33:19 +00:00
Tiago Cunha
39628e8280 Add format.c to the list of sources. 2011-09-21 16:32:31 +00:00
Tiago Cunha
40af1a854c Sync OpenBSD patchset 953:
Add initial framework for more powerful formatting of command output and
use it for list-{panes,windows,sessions}. This allows more descriptive
replacements (such as #{session_name}) and conditionals.

Later this will be used for status_replace and list-keys and other
places.
2011-09-21 16:31:15 +00:00
Nicholas Marriott
fb5b958837 Add build instructions based on diff from Frank Terbeck. 2011-09-15 12:58:39 +00:00
Nicholas Marriott
99f78340af Use %u for process group on Sun OS. 2011-09-11 23:54:32 +00:00
Tiago Cunha
4a01da19df Sync OpenBSD patchset 951:
Support \ for line continuation in the configuration file, from Julius
Plenz.
2011-08-25 21:14:23 +00:00
Tiago Cunha
d390a90bf0 Sync OpenBSD patchset 950:
Add pane-base-index option, from Ben Barbour.
2011-08-25 21:13:45 +00:00
Tiago Cunha
c41a93d130 Sync OpenBSD patchset 949:
Add a tty_bell wrapper function, from Dylan Alex Simon.
2011-08-25 21:12:52 +00:00
Tiago Cunha
0a4fd0f7a4 libm isn't needed anymore. 2011-08-25 21:12:10 +00:00
Tiago Cunha
a54e670301 Sync OpenBSD patchset 948:
There is no need to use sqrt()/INFINITY here which simplifies the code
and makes it more portable, from Havard Eidnes.
2011-08-25 21:11:16 +00:00
Tiago Cunha
2651c0d69c Sync OpenBSD patchset 947:
Fix a couple of memory leaks, from marcel partap.
2011-08-21 12:39:34 +00:00
Tiago Cunha
87a2a13f68 Sync OpenBSD patchset 946:
Add a -r flag to switch-client to toggle the client read-only flag. From
Johan Commelin.
2011-08-21 12:38:55 +00:00
Tiago Cunha
5775074f73 Sync OpenBSD patchset 945:
Add up/down/left/right keys in vi edit mode. From "livibetter" SF bug
3385651.
2011-08-21 12:37:26 +00:00
Tiago Cunha
abb4af7a14 Sync OpenBSD patchset 944:
Use key_bindings_remove for unbind-key -a to allow it to work from key
bindings. From "miaout17" SF bug 3392063.
2011-08-21 12:36:43 +00:00
Tiago Cunha
b9bbe1d81c Sync OpenBSD patchset 943:
Correctly skip existing numbers when generating the name for a new
session.
2011-08-21 12:35:47 +00:00
Nicholas Marriott
cd62411d78 +. 2011-08-16 09:58:49 +00:00
Nicholas Marriott
e39c5a9e14 +. 2011-08-15 09:01:23 +00:00
Nicholas Marriott
b2fe881307 +. 2011-08-14 15:36:15 +00:00
Tiago Cunha
b6659dc563 Sync OpenBSD patchset 942:
fix error in previous;
2011-08-04 17:06:10 +00:00
Tiago Cunha
3ce1b91b1b Sync OpenBSD patchset 941:
Extend the mode-mouse option to add a third choice which means the mouse
does not enter copy mode. Patch from SF bug 3374493.

In future the mode-mouse option is likely to die and be broken into
several smaller options.
2011-08-04 17:05:35 +00:00
Tiago Cunha
2589d117b0 Sync OpenBSD patchset 940:
Do not require a client here, or pipe-pane will not work from the
command line.
2011-08-04 17:04:08 +00:00
Tiago Cunha
8aec4c93eb $Id$ not $OpenBSD$. 2011-08-04 17:03:29 +00:00
Tiago Cunha
9960a06a67 Sync OpenBSD patchset 939:
Sort options alphabetically, from Tiago Cunha.
2011-08-04 17:01:55 +00:00
Nicholas Marriott
0ecb11fe4f Add. 2011-07-30 17:47:21 +00:00
Nicholas Marriott
7d604ab717 Add. 2011-07-30 17:44:24 +00:00
Nicholas Marriott
ee5e97926d Fix --enable-static and add a different check for b64_ntop that might work on
OS X.
2011-07-27 09:31:08 +00:00
Nicholas Marriott
e9ebdac3dd Can't use the same va_list twice, from Emanuele Giaquinta. 2011-07-25 09:56:43 +00:00
Nicholas Marriott
5339b8ce3a Typo. 2011-07-22 15:10:24 +00:00
Nicholas Marriott
20134fa9f4 Compatibility for b64_ntop, missing from some alternative libc. 2011-07-22 10:49:33 +00:00
Nicholas Marriott
1f01dd8c0a +. 2011-07-19 01:47:26 +00:00
Nicholas Marriott
25eb48aea3 Only get -lrt when needed, from Pietro Cerutti. 2011-07-19 01:35:33 +00:00
Nicholas Marriott
e5cee89727 Typo, from Si Feng. 2011-07-19 01:31:00 +00:00
Tiago Cunha
d86c6b2fff Bump version and create a debug build by default. 2011-07-09 16:24:44 +00:00
Tiago Cunha
5175db270d Changes for 1.5. 2011-07-09 16:01:55 +00:00
Tiago Cunha
8d63a99390 Releases don't have debugging enabled. 2011-07-09 16:00:16 +00:00
Tiago Cunha
f16b6aeabb Use an empty CFLAGS by default to prevent autoconf from setting it when
debugging isn't enabled.
2011-07-09 15:57:56 +00:00
Tiago Cunha
df69ee07e2 Delete subversion directories before the actual tarball is created. 2011-07-09 13:45:24 +00:00
Tiago Cunha
31def00f59 Done. 2011-07-09 09:47:12 +00:00
Tiago Cunha
27bd09f075 HP-UX should work now. 2011-07-09 09:46:15 +00:00
Tiago Cunha
391f1f08c0 Expand the Id keyword. 2011-07-09 09:42:33 +00:00
Tiago Cunha
8357a55d76 Add missing $Id$. 2011-07-09 09:34:04 +00:00
Tiago Cunha
5f38f8cd64 Sync OpenBSD patchset 938:
Unused variable.
2011-07-09 09:05:05 +00:00
Nicholas Marriott
5ae4b4acc0 Pass the right size to calloc (* not **). 2011-07-09 01:38:01 +00:00
Tiago Cunha
67e70770c8 Sync OpenBSD patchset 936:
Do not continue to send data to suspended/locked clients or there will
be a huge rush of it after they are resumed/unlocked. The main output
path was fine but status line updates and the terminal state reset code
were missed.
2011-07-08 22:58:30 +00:00
Tiago Cunha
bcacbb1a89 Sync OpenBSD patchset 935:
flags[] should be initialized. From Thomas Adam.
2011-07-08 16:44:06 +00:00
Tiago Cunha
bba822105b Sync OpenBSD patchset 934:
Make confirm-before prompt customizable with -p option like
command-prompt. Also move responsibility for calling status_replace into
status_prompt_{set,update} and add #W and #P to the default kill-window
and kill-pane prompts. By Tiago Cunha.
2011-07-08 08:42:03 +00:00
Tiago Cunha
dc2c174496 Sync OpenBSD patchset 933:
Fix a couple of comments.
2011-07-08 08:40:35 +00:00
Tiago Cunha
6c4166ce20 Sync OpenBSD patchset 932:
Show full targets for lsp/lsw -a.
2011-07-05 10:43:59 +00:00
Tiago Cunha
5dad3166f9 Sync OpenBSD patchset 931:
Use screen_reinit for respawn-pane to keep history and call input_init
for respawn-window to break out of waiting for DCS/OSC to finish.
2011-07-05 10:42:09 +00:00
Nicholas Marriott
e80e7b38bb Done too. 2011-07-04 14:04:55 +00:00
Nicholas Marriott
6457052a93 Done too. 2011-07-04 13:54:43 +00:00
Nicholas Marriott
d91bf78e8a These are done. 2011-07-04 13:36:12 +00:00
Tiago Cunha
bc8d09ef84 Sync OpenBSD patchset 930:
Change the list-keys format so that it shows the keys using actual tmux
commands which should be able to be directly copied into the config
file. From Markus Schnalke, tweaked by me.
2011-07-04 08:26:41 +00:00
Tiago Cunha
8144e5cb7e Sync OpenBSD patchset 929:
Add an option to trigger the terminal bell when there is an alert, from
Marco Beck.
2011-07-04 08:23:39 +00:00
Tiago Cunha
fce026eb32 Sync OpenBSD patchset 928:
Include the existing window and session name in the prompt when renaming
and add a new key binding ($) for rename session. From Tiago Cunha.
2011-07-04 08:22:37 +00:00
Tiago Cunha
e097f0b4ee Sync OpenBSD patchset 927:
Allow the initial context on prompts to be set with the new -I option to
command-prompt. From Tiago Cunha.
2011-07-03 21:52:50 +00:00
Tiago Cunha
ff7343c203 Sync OpenBSD patchset 926:
PANE_FREEZE doesn't do anything anymore, so remove it.
2011-07-03 21:51:17 +00:00
Tiago Cunha
3d47b5cd07 Sync OpenBSD patchset 925:
Add a couple of extra xterm-style keys that gnome terminal provides,
from Dustin Kirkland.
2011-07-03 21:50:27 +00:00
Nicholas Marriott
6ce5ed60a6 +. 2011-06-27 23:04:44 +00:00
Nicholas Marriott
c80f75f4f4 tparm requires 10 arguments on Solaris. 2011-06-26 23:59:23 +00:00
Nicholas Marriott
4564624f2c +. 2011-06-26 23:18:05 +00:00
Nicholas Marriott
84aa9c34f8 trunk/tmux not tmux/tmux 2011-06-24 13:13:21 +00:00
Nicholas Marriott
db7d3a3966 Tweaks, one thing I have an uncommitted fix for. 2011-06-23 23:27:07 +00:00
Nicholas Marriott
f513898e92 PatchSet 924
Date: 2011/06/05 12:19:03
Author: nicm
Branch: HEAD
Tag: (none)
Log:
Add a respawn-pane command, from Marcel Partap.
2011-06-23 19:23:12 +00:00
Nicholas Marriott
7407459ed1 Removed file. 2011-06-23 19:22:01 +00:00
Nicholas Marriott
fa0f10d77a PatchSet 923
Date: 2011/06/05 11:53:05
Author: nicm
Branch: HEAD
Tag: (none)
Log:
Get rid of the layout string code which tries to walk through the layout
hierarchy and instead just look at what panes are actually in the window.
2011-06-23 19:21:26 +00:00
Nicholas Marriott
ddade84e0a PatchSet 922
Date: 2011/05/30 22:02:28
Author: nicm
Branch: HEAD
Tag: (none)
Log:
Fix a typo, spotted by Michal Mazurek..
2011-06-23 19:19:08 +00:00
Nicholas Marriott
1cf916ca73 Add. 2011-06-05 11:03:10 +00:00
Nicholas Marriott
12544ccd41 Add. 2011-06-05 10:29:33 +00:00
Nicholas Marriott
dac6e55e0a Add. 2011-06-05 10:21:32 +00:00
Tiago Cunha
213544a30a $Id$ not $OpenBSD$. 2011-05-29 15:13:36 +00:00
Tiago Cunha
159faa4ed7 Sync OpenBSD patchset 921:
Trim another useless if statement, from Ailin Nemui.
2011-05-26 20:18:06 +00:00
Tiago Cunha
f9cb06cf2c Sync OpenBSD patchset 920:
Memory leak in error path, from Tiago Cunha.
2011-05-26 20:16:17 +00:00
Tiago Cunha
28427efbac Sync OpenBSD patchset 819:
Nuke a redundant if statement, from Tiago Cunha.
2011-05-26 20:12:07 +00:00
Nicholas Marriott
e14bf9bb8f One of these gives us b64_ntop. 2011-05-26 10:35:07 +00:00
Nicholas Marriott
d0f362a503 Add. 2011-05-26 07:00:48 +00:00
Nicholas Marriott
ea6844b5b7 Bye bye stray tmux directory. 2011-05-23 17:58:45 +00:00
Nicholas Marriott
def72b2985 ... 2011-05-22 20:58:40 +00:00
Nicholas Marriott
a0b271a8a0 ... 2011-05-22 20:58:29 +00:00
Nicholas Marriott
7a529cc32a ... 2011-05-22 20:56:56 +00:00
Nicholas Marriott
f89d0c3c2c ... 2011-05-22 20:55:40 +00:00
Nicholas Marriott
4bf85ecbb0 ... 2011-05-22 20:53:55 +00:00
Nicholas Marriott
cae34a8ce7 . 2011-05-22 20:48:57 +00:00
Nicholas Marriott
07377d5a97 Update links. 2011-05-22 20:30:21 +00:00
Tiago Cunha
b5b630229a Sync OpenBSD patchset 918:
tweak the TERMINFO section; ok nicm
2011-05-22 16:26:58 +00:00
Tiago Cunha
d256660a78 Sync OpenBSD patchset 917:
Pass prompts through status_replace so that they can be more helpful
(such as showing the previous session name when renaming). From Tiago
Cunha.
2011-05-22 16:26:38 +00:00
Tiago Cunha
b2f301f4e2 Sync OpenBSD patchset 916:
Support DECSCUSR sequence to set the cursor style with two new
terminfo(5) extensions, Cs and Csr. Written by Ailin Nemui.
2011-05-22 16:26:09 +00:00
Tiago Cunha
719755574d Sync OpenBSD patchset 915:
Support xterm(1) cursor colour change sequences through terminfo(5) Cc
(set) and Cr (reset) extensions. Originally by Sean Estabrooks, tweaked
by me and Ailin Nemui.
2011-05-22 16:25:02 +00:00
Tiago Cunha
89f35125b4 Sync OpenBSD patchset 914:
Support setting the xterm clipboard when copying from copy mode using
the xterm escape sequence for the purpose (if xterm is configured to
allow it).

Written by and much discussed Ailin Nemui, guidance on
xterm/termcap/terminfo from Thomas Dickey.
2011-05-22 16:23:07 +00:00
Nicholas Marriott
e7f3be9187 Someone mentioned this at LinuxTag as well. 2011-05-21 11:22:47 +00:00
Nicholas Marriott
0cad8a5808 Add. 2011-05-18 20:39:24 +00:00
Tiago Cunha
69e0aabcdf Sync OpenBSD patchset 913:
Add three new copy-mode commands - select-line, copy-line,
copy-end-of-line. From Dave Disser and Randy Stauner a while back.
2011-05-18 20:35:36 +00:00
Tiago Cunha
3cb428bc7e Sync OpenBSD patchset 912:
Use xfree not free, from Tiago Cunha.
2011-05-18 20:33:55 +00:00
Tiago Cunha
e0fcd3b247 Sync OpenBSD patchset 911:
Use button mouse mode not any for copy mode, fixes issues with
putty. From Ailin Nemui.
2011-05-18 20:33:24 +00:00
Tiago Cunha
21140d426d Sync OpenBSD patchset 910:
Reset last pane properly when using break-pane as well, fixes a problem
reported to Debian by Hannes von Haugwitz (bug 622677).
2011-05-18 20:32:47 +00:00
Tiago Cunha
13d5ac6f9e Sync OpenBSD patchset 909:
Reset last pane on swap-pane across windows, fixes crash noticed by hsim
at gmx.li.
2011-05-18 20:32:04 +00:00
Tiago Cunha
1e7cea407d Sync OpenBSD patchset 908:
Only select pane on click, not drag. From hsim at gmx.li.
2011-05-18 20:31:32 +00:00
Tiago Cunha
bb38112ec8 Sync OpenBSD patchset 907:
Fix a couple of memory leaks, from Tiago Cunha.
2011-05-18 20:31:00 +00:00
Tiago Cunha
1d2b487c84 Sync OpenBSD patchset 906:
Fix a memory leak if cmd_pane_session succeeds, from Tiago Cunha.
2011-05-18 20:30:36 +00:00
Tiago Cunha
4efd45628d Sync OpenBSD patchset 905:
Add a new option, mouse-resize-pane. When on, panes may be resized by
dragging their borders. From hsim at gmx.li.
2011-05-18 20:30:14 +00:00
Tiago Cunha
4fcbf4b872 Sync OpenBSD patchset 904:
Use the tsl and fsl terminfo(5) capabilities to update terminal title
and automatically fill them in on terminals with the XT capability
(which means their title setting is xterm-compatible). From hsim at
gmx.li.
2011-05-18 20:28:43 +00:00
Nicholas Marriott
046e8363b4 +. 2011-05-18 19:52:33 +00:00
Nicholas Marriott
992dbdedd8 +. 2011-05-18 17:57:59 +00:00
Nicholas Marriott
d344816d91 Update from Tiago Resende. 2011-05-18 17:47:33 +00:00
Nicholas Marriott
75e7c7eed5 Add some stuff mentioned to me at LinuxTag. 2011-05-17 18:20:04 +00:00
Nicholas Marriott
4b6babcfa2 +. 2011-05-10 22:05:04 +00:00
Tiago Cunha
268a2efb16 Sync OpenBSD patchset 903:
Change window with mouse wheel over status line if mouse-select-window
is on, from marcel partap.
2011-05-05 10:12:33 +00:00
Tiago Cunha
b5812013ef Sync OpenBSD patchset 901:
Don't use strnvis for the title as it breaks UTF-8. set-titles is now
off by default and we have to trust the terminal can understand what we
send it anyway so there isn't any harm.
2011-05-05 10:10:57 +00:00
Tiago Cunha
a734b41fda Sync OpenBSD patchset 900:
Check if mouse-select-pane is ON not off when setting mouse flags,
reported by oga.
2011-05-05 10:03:05 +00:00
Tiago Cunha
4846af8f95 Sync OpenBSD patchset 899:
Only redraw the status line on command update, not the entire client
(big DOH).
2011-05-05 10:02:36 +00:00
Tiago Cunha
341f67e827 Sync OpenBSD patchset 898:
Provide #h for short hostname (no domain) from Michal Mazurek.
2011-04-25 20:35:22 +00:00
Tiago Cunha
38611d3207 Sync OpenBSD patchset 897:
Tweak copy behaviour slightly in vi mode to be closer to real vi. From
Tiago Resende.
2011-04-25 20:34:26 +00:00
Tiago Cunha
215ee46106 Sync OpenBSD patchset 896:
When mode-mouse is on (it is off by default), automatically enter copy
mode when the mouse is dragged or the mouse wheel is used. Also exit
copy mode when the mouse wheel is scrolled off the bottom. Discussed
with and written by hsim at gmx dot li.
2011-04-25 20:33:42 +00:00
Tiago Cunha
d5150484d1 Sync OpenBSD patchset 895:
POSIX only guarantees uname() will return a non-negative value on
success.

ok nicm@
2011-04-25 20:32:03 +00:00
Nicholas Marriott
656a668473 Add. 2011-04-19 20:21:42 +00:00
Nicholas Marriott
7aafee7e48 |PatchSet 894
|Date: 2011/04/18 21:57:16
|Author: nicm
|Branch: HEAD
|Tag: (none)
|Log:
|The mouse should only work in copy mode if mode-mouse is set, not just
|mouse-select-pane.
2011-04-18 22:03:55 +00:00
Nicholas Marriott
dc6bd98425 |PatchSet 893
|Date: 2011/04/18 20:49:05
|Author: nicm
|Branch: HEAD
|Tag: (none)
|Log:
|Add an option (mouse-select-window) which allows the mouse to be used by
|clicking on the status line, written by hsim at gmx dot li.
2011-04-18 21:07:58 +00:00
Nicholas Marriott
34a331aa99 |PatchSet 891
|Date: 2011/04/17 20:28:09
|Author: nicm
|Branch: HEAD
|Tag: (none)
|Log:
|Add -t to list-clients, based on a diff from Zac Sprackett.
2011-04-18 21:07:12 +00:00
Nicholas Marriott
6351940744 |PatchSet 890
|Date: 2011/04/17 20:21:19
|Author: nicm
|Branch: HEAD
|Tag: (none)
|Log:
|Fix character position check, from Tiago Resende.
2011-04-18 21:06:49 +00:00
Nicholas Marriott
65fc8ef43a |PatchSet 889
|Date: 2011/04/11 17:44:36
|Author: nicm
|Branch: HEAD
|Tag: (none)
|Log:
|-s comes before -t and also add -s to command syntax. Prompted by jmc.
2011-04-18 21:06:25 +00:00
Nicholas Marriott
d5ab166307 Sync man page. 2011-04-18 21:05:24 +00:00
Nicholas Marriott
a6456f4db3 PatchSet 887
Date: 2011/04/10 04:20:59
Author: guenther
Branch: HEAD
Tag: (none)
Log:
Switch back from KERN_PROC2/kinfo_proc2 to KERN_PROC/kinfo_proc now
that we've got name we want for the API we want
2011-04-18 21:03:42 +00:00
Nicholas Marriott
dd34cc012a |PatchSet 886
|Date: 2011/04/09 21:00:29
|Author: nicm
|Branch: HEAD
|Tag: (none)
|Log:
|Since buffers are now global, bump the default buffer-limit a bit higher
|to 20 rather than 9.
2011-04-18 21:01:44 +00:00
Nicholas Marriott
2c0846569d Window content backup script from Victor J Orlikowski. 2011-04-17 19:36:35 +00:00
Nicholas Marriott
afbbdff581 Add tmuxinator. 2011-04-15 22:10:20 +00:00
Nicholas Marriott
cb60ea1bdb Add some third party stuff. 2011-04-15 21:56:38 +00:00
Nicholas Marriott
3aee28c58b +. 2011-04-15 19:01:51 +00:00
Nicholas Marriott
088232e0e0 Add. 2011-04-12 16:58:49 +00:00
Nicholas Marriott
5e5acbeccd a independent -> an independent. 2011-04-11 22:59:57 +00:00
Nicholas Marriott
f0843d2173 Entry on italics from Tiago Resende. 2011-04-11 07:14:54 +00:00
Nicholas Marriott
457147d59d Add -s option to detach all clients attached to a session, from Zac
Sprackett.
2011-04-11 06:44:56 +00:00
Nicholas Marriott
75f218dc73 If the terminal supports sitm for italics, use it instead of standout
(smso). From Tiago Resende.
2011-04-09 07:48:58 +00:00
Nicholas Marriott
1d00f88757 Manual date. 2011-04-06 22:31:23 +00:00
Nicholas Marriott
e5f4bf3f3e |PatchSet 884
|Date: 2011/04/06 22:51:31
|Author: nicm
|Branch: HEAD
|Tag: (none)
|Log:
|Change so that an empty session name always means the current sessions
|even if given with, for example, -t '', and explicitly forbid empty
|session names and those containing a : when they are created.
2011-04-06 22:29:26 +00:00
Nicholas Marriott
13c54a04a0 |PatchSet 883
|Date: 2011/04/06 12:36:26
|Author: miod
|Branch: HEAD
|Tag: (none)
|Log:
|Avoid using NULL in non-pointer contexts: use 0 for integer values and '\0'
|for chars.
2011-04-06 22:24:20 +00:00
Nicholas Marriott
4e452a2e11 |PatchSet 882
|Date: 2011/04/05 20:37:01
|Author: nicm
|Branch: HEAD
|Tag: (none)
|Log:
|Add a flag to cmd_find_session so that attach-session can prefer
|unattached sessions when choosing the most recently used (if -t is not
|given). Suggested by claudio@.
2011-04-06 22:24:01 +00:00
Nicholas Marriott
ae5954d30a |PatchSet 881
|Date: 2011/04/05 19:55:38
|Author: nicm
|Branch: HEAD
|Tag: (none)
|Log:
|Bind C-u to delete-line in vi mode like ksh does, suggested by thib.
2011-04-06 22:23:30 +00:00
Nicholas Marriott
01f5f041d3 |PatchSet 880
|Date: 2011/04/01 17:59:11
|Author: nicm
|Branch: HEAD
|Tag: (none)
|Log:
|"or" should be on a line on its own here so it is not emphasised as
|well.
2011-04-06 22:23:14 +00:00
Nicholas Marriott
d9cb059e34 |PatchSet 879
|Date: 2011/03/29 22:09:13
|Author: nicm
|Branch: HEAD
|Tag: (none)
|Log:
|For convenience, work out what type of option is being set by name
|regardless of the -s or -w flags (these remain documented however).
2011-04-06 22:22:49 +00:00
Nicholas Marriott
ec3be580ec |PatchSet 878
|Date: 2011/03/29 22:07:08
|Author: nicm
|Branch: HEAD
|Tag: (none)
|Log:
|Checking for particular options and redrawing is not necessary as we
|already redraw unconditionally.
2011-04-06 22:22:25 +00:00
Nicholas Marriott
02462e5e57 |PatchSet 877
|Date: 2011/03/29 21:31:22
|Author: nicm
|Branch: HEAD
|Tag: (none)
|Log:
|Update an out-of-date and inaccurate comment.
2011-04-06 22:21:24 +00:00
Nicholas Marriott
ffce6b34b2 |PatchSet 876
|Date: 2011/03/29 20:30:16
|Author: nicm
|Branch: HEAD
|Tag: (none)
|Log:
|Change -t on display-message to be target-pane for the #[A-Z]
|replacements and add -c as target-client.
2011-04-06 22:21:02 +00:00
Nicholas Marriott
108fb38cbc |PatchSet 875
|Date: 2011/03/29 00:13:00
|Author: nicm
|Branch: HEAD
|Tag: (none)
|Log:
|Add -a and -s options to lsp to list all panes in the server or session
|respectively. Likewise add -s to lsw. From Ben Boeckel.
2011-04-06 22:20:16 +00:00
Nicholas Marriott
0a2b3492c3 |PatchSet 874
|Date: 2011/03/28 21:17:39
|Author: nicm
|Branch: HEAD
|Tag: (none)
|Log:
|Allow a start and end line to be specified for capture-pane which may be
|negative to capture part of the history. Prompted by request from Victor
|J Orlikowski.
2011-04-06 22:19:42 +00:00
Nicholas Marriott
8ab7fcf7eb |PatchSet 873
|Date: 2011/03/28 20:44:31
|Author: nicm
|Branch: HEAD
|Tag: (none)
|Log:
|Style: uint -> u_int and a missing else.
2011-04-06 22:18:56 +00:00
Nicholas Marriott
129f0dc893 |PatchSet 872
|Date: 2011/03/27 21:36:19
|Author: nicm
|Branch: HEAD
|Tag: (none)
|Log:
|Set the terminal blocking again earlier, before sending the reset
|sequences.
2011-04-06 22:18:05 +00:00
Nicholas Marriott
2b508f7f6b |PatchSet 871
|Date: 2011/03/27 21:31:25
|Author: nicm
|Branch: HEAD
|Tag: (none)
|Log:
|Don't include meta twice when working out the flags to output for
|xterm-style keys - bit 3 is accepted on input but not on output. Also a
|style nit in the header.
2011-04-06 22:17:33 +00:00
Nicholas Marriott
536fc24653 PatchSet 870
Date: 2011/03/27 21:27:26
Author: nicm
Branch: HEAD
Tag: (none)
Log:
Give each pane created in a tmux server a unique id (starting from 0),
put it in the TMUX_PANE environment variable and accept it as a
target. Suggested by and with testing and tweaks from Ben Boeckel.
2011-04-06 22:16:33 +00:00
Nicholas Marriott
95832241aa Add a couple of items. 2011-04-06 20:52:04 +00:00
Nicholas Marriott
8091dcdd97 Add. 2011-03-28 20:14:30 +00:00
Nicholas Marriott
f8dbfb0aa7 Add. 2011-03-28 18:59:37 +00:00
Nicholas Marriott
b9216d9566 Done. 2011-03-27 21:02:27 +00:00
Micah Cowan
a9eb5e12ec Fix to properly wrap wide characters. 2011-03-24 17:03:29 +00:00
Tiago Cunha
164c2cbcb0 Sync OpenBSD patchset 868:
Fix an incorrect test which was always true (oupper is always < olower),
from Yusuke ENDOH.
2011-03-19 23:32:01 +00:00
Tiago Cunha
20e17604b5 Sync OpenBSD patchset 867:
Prevent tiled producing a corrupt layout when only one column is needed,
from Karl Ferdinand Ebert.
2011-03-19 23:31:08 +00:00
Tiago Cunha
a0295b4c2f Sync OpenBSD patchset 866:
Support passing through escape sequences to the underlying terminal by
using DCS with a "tmux;" prefix. Escape characters in the sequences must
be doubled. For example:

$ printf '\033Ptmux;\033\033]12;red\007\033\\'

Will pass \033]12;red\007 to the terminal (and change the cursor colour
in xterm). From Kevin Goodsell.
2011-03-19 23:30:37 +00:00
Tiago Cunha
9bc44043a4 Sync OpenBSD patchset 864:
Fix a typo that meant we did not reset the background colour when it was
omitted in a 256-colour SGR ([48;5m). From Yusuke ENDOH.
2011-03-19 23:28:30 +00:00
Tiago Cunha
d0cca3924e Sync OpenBSD patchset 863:
Add a -P option to detach to HUP the client's parent process (usually
causing it to exit as well).
2011-03-19 23:27:35 +00:00
Nicholas Marriott
34bb013b92 Use the right asprintf since we don't support truly broken platforms right now. 2011-03-04 23:39:41 +00:00
Micah Cowan
4cb976b408 Fix sscanf that was guaranteed to always fail. 2011-03-04 23:13:56 +00:00
Micah Cowan
c0888f3fd1 Make sure non-UTF8 mouse coordinates are kept to 8-bit values. 2011-03-04 20:36:59 +00:00
Nicholas Marriott
9def6baaba +. 2011-02-28 21:10:33 +00:00
Tiago Cunha
c7624fd25d Sync OpenBSD patchset 862:
Size on split-window is -l not -s. Doh.
2011-02-15 15:26:54 +00:00
Tiago Cunha
32de1d52ea Sync OpenBSD patchset 861:
Don't require -d with -x or -y since it could be in the config file.
2011-02-15 15:25:48 +00:00
Tiago Cunha
677286bc0e Sync OpenBSD patchset 860:
Redraw pane borders when switching to last pane.
2011-02-15 15:25:12 +00:00
Tiago Cunha
19e81ffda5 Sync OpenBSD patchset 859:
Free old argument even if setting to NULL.
2011-02-15 15:24:40 +00:00
Tiago Cunha
d718a14bd0 Sync OpenBSD patchset 858:
Accept tcgetattr/tcsetattr failure, fixes problems with fatal() if the
terminal disappears while locked.
2011-02-15 15:24:00 +00:00
Tiago Cunha
04ce5cc2d1 Sync OpenBSD patchset 857:
Use input_clear to reset the APC, DCS, OSC state or it could be reused
improperly by a later state. From Kevin Goodsell.
2011-02-15 15:21:14 +00:00
Tiago Cunha
065384056b Sync OpenBSD patchset 856:
Unused declaration.
2011-02-15 15:20:38 +00:00
Tiago Cunha
3d7b8105e1 Sync OpenBSD patchset 855:
Simplify the way jobs work and drop the persist type, so all jobs are
fire-and-forget.

Status jobs now managed with two trees of output (new and old), rather
than storing the output in the jobs themselves. When the status line is
processed any jobs which don't appear in the new tree are started and
the output from the old tree displayed. When a job finishes it updates
the new tree with its output and that is used for any subsequent
redraws. When the status interval expires, the new tree is moved to the
old so that all jobs are run again.

This fixes the "#(echo %H:%M:%S)" problem which would lead to thousands
of identical persistent jobs and high memory use (this can still be
achieved by adding "sleep 30" but that is much less likely to happen by
accident).
2011-02-15 15:20:03 +00:00
Tiago Cunha
3b56ebce6d Sync OpenBSD patchset 854:
Use LIST_* not SLIST_*.
2011-02-15 15:12:28 +00:00
Tiago Cunha
2ab568fa88 Sync OpenBSD patchset 853:
When clearing the entire screen, clear lines that are used into the
history like xterm does. Requested ages ago by someone I've forgotten.
2011-02-15 15:10:47 +00:00
Tiago Cunha
4e4568cade Sync OpenBSD patchset 852:
Check if the index is in use and fail before creating the child process,
rather than leaving a stray child on failure.
2011-02-15 15:09:52 +00:00
Tiago Cunha
d0d1c0e486 Sync OpenBSD patchset 848:
Set $TMUX without the session when background jobs are run.
2011-02-14 23:11:33 +00:00
Nicholas Marriott
d37650dc4f Spacing. 2011-02-14 20:39:40 +00:00
Nicholas Marriott
cf3b73167d Expand an entry. 2011-02-12 15:51:11 +00:00
Nicholas Marriott
5532615bc0 Solaris is SunOS. 2011-02-11 23:31:15 +00:00
Nicholas Marriott
0fa8d18775 Remove some that are done and some that are duplicates or no longer needed. 2011-01-26 02:05:02 +00:00
Nicholas Marriott
5cbdd84686 While here, maximum percentage is 100 not INT_MAX. Oops. 2011-01-23 15:49:32 +00:00
Nicholas Marriott
2be75a0129 Size is -l not -s. 2011-01-23 15:47:31 +00:00
Tiago Cunha
ec3a764c76 Make bind-key accept characters with the top-bit-set and print them as octal. 2011-01-22 22:31:09 +00:00
Tiago Cunha
e3defd9b25 Sync OpenBSD patchset 847:
Fix bind-key -t.
2011-01-22 00:00:23 +00:00
Tiago Cunha
1930181b18 Sync OpenBSD patchset 846:
Only set a mouse mode for mouse-select-pane if none already set by the
mode (any will do).
2011-01-21 23:56:53 +00:00
Tiago Cunha
332bfbf273 Sync OpenBSD patchset 845:
Mouse highlight mode (1001) requires a program to cooperate so
supporting it through tmux is not as easy as this, remove it for now.
2011-01-21 23:56:11 +00:00
Tiago Cunha
7a68cff1db Sync OpenBSD patchset 844:
Support -x and -y for new-session to specify the initial size of the
window if created detached with -d.
2011-01-21 23:55:26 +00:00
Tiago Cunha
6d9fe6c3aa Sync OpenBSD patchset 843:
The maximum history-limit was accidentally reduced, fix it back to INT_MAX.
2011-01-21 23:54:19 +00:00
Tiago Cunha
c2ed0186de Sync OpenBSD patchset 842:
Clarify alternate-screen description a little.
2011-01-21 23:53:45 +00:00
Tiago Cunha
3866988f87 Sync OpenBSD patchset 841:
Er, fix next and previous session functions to actually work, part 2.
2011-01-21 23:53:01 +00:00
Tiago Cunha
43f8d62f6a Sync OpenBSD patchset 840:
Fix next and previous session functions to actually work.
2011-01-21 23:52:36 +00:00
Tiago Cunha
a880639f48 Sync OpenBSD patchset 839:
Log termios backspace for each client since it is used to recognise
backspace input.
2011-01-21 23:51:36 +00:00
Tiago Cunha
57eb948c48 Sync OpenBSD patchset 838:
Use TMPDIR if set, from Han Boetes.
2011-01-21 23:46:50 +00:00
Tiago Cunha
6c3186a19a Sync OpenBSD patchset 837:
unbind-key -a is allowed no arguments.
2011-01-21 23:46:09 +00:00
Tiago Cunha
10a5a2175e Sync OpenBSD patchset 836:
Remove a bit of text that makes exit-unattached description unclear.
2011-01-21 23:45:34 +00:00
Tiago Cunha
be7cec5640 Sync OpenBSD patchset 835:
Add missing arguments to some options.
2011-01-21 23:45:04 +00:00
Tiago Cunha
492e3aa437 Sync OpenBSD patchset 834:
Move all calls to fcntl(...O_NONBLOCK) into a function and clear the
flag on the stdio file descriptors before closing them (fixes things
like "tmux ls && cat").
2011-01-21 23:44:13 +00:00
Tiago Cunha
6b19621112 Sync OpenBSD patchset 833:
Accept colours of the hex form #ffffff and translate to the nearest from
the xterm(1) 256-colour set.
2011-01-21 23:42:14 +00:00
Tiago Cunha
324ffe20e9 Link with libm due to the upcoming patchset. 2011-01-21 23:40:30 +00:00
Nicholas Marriott
38f169113e Support for HP-UX. 2011-01-21 20:35:20 +00:00
Nicholas Marriott
e34c6fd187 Only have one asprintf implementation, that's likely to always work. 2011-01-21 20:03:18 +00:00
Nicholas Marriott
ac01c2025a Whoops, did not mean to do this. 2011-01-13 19:59:48 +00:00
Nicholas Marriott
e08a40be56 osdep-linux.c 2011-01-13 19:58:47 +00:00
Nicholas Marriott
abd1f615b2 Trim spaces. 2011-01-10 22:45:10 +00:00
Nicholas Marriott
a7b6445cc3 Better __progname check. 2011-01-10 22:12:31 +00:00
Nicholas Marriott
96fe3b26c1 Copy osdep-unknown.c for AIX to make @PLATFORM@ work. 2011-01-10 22:00:47 +00:00
Nicholas Marriott
93fd9cc29d Check for optarg, optind, optreset. 2011-01-10 21:51:56 +00:00
Nicholas Marriott
87841b4f91 +. 2011-01-09 18:57:05 +00:00
Nicholas Marriott
676c62647c +. 2011-01-07 19:01:19 +00:00
Tiago Cunha
30f6d9b167 Sync OpenBSD patchset 813:
Add a function to create window flags rather than doing the same thing
in two places. From Thomas Adam.
2011-01-07 16:55:40 +00:00
Tiago Cunha
1cb579d0fd Bring the last remaining bits of dist.mk. 2011-01-07 15:09:04 +00:00
Tiago Cunha
3d4ebeb1b0 Sync OpenBSD patchset 832:
Whoops, command-prompt can take 0 or 1 argument.
2011-01-07 15:04:51 +00:00
Tiago Cunha
0fc4353fb3 Remove dead files entries. 2011-01-07 15:04:24 +00:00
Tiago Cunha
ca413cf270 Sync OpenBSD patchset 831:
Now that parsing is common, merge some of the small, related commands
together to use the same code.

Also add some arguments (such as -n and -p) to some commands to match
existing commands.
2011-01-07 15:02:38 +00:00
Tiago Cunha
b2b5d88f3f Sync OpenBSD patchset 830:
argc will be 1 not 2 with no option value.
2011-01-07 14:51:54 +00:00
Tiago Cunha
ecec113b63 cmd-generic.c isn't needed anymore due to OpenBSD patchset 829. 2011-01-07 14:50:54 +00:00
Tiago Cunha
0740d3dbb8 Remove compat include. 2011-01-07 14:46:57 +00:00
Tiago Cunha
9301eeb4dd More _SOURCES. 2011-01-07 14:46:13 +00:00
Tiago Cunha
1df427bc7b Sync OpenBSD patchset 829:
Clean up and simplify tmux command argument parsing.

Originally, tmux commands were parsed in the client process into a
struct with the command data which was then serialised and sent to the
server to be executed. The parsing was later moved into the server (an
argv was sent from the client), but the parse step and intermediate
struct was kept.

This change removes that struct and the separate parse step. Argument
parsing and printing is now common to all commands (in arguments.c) with
each command left with just an optional check function (to validate the
arguments at parse time), the exec function and a function to set up any
key bindings (renamed from the old init function).

This is overall more simple and consistent.

There should be no changes to any commands behaviour or syntax although
as this touches every command please watch for any unexpected changes.
2011-01-07 14:45:34 +00:00
Tiago Cunha
219442cff7 Sync OpenBSD patchset 828:
Support for UTF-8 mouse input (\033[1005h). This was added in xterm 262
and supports larger terminals than the older way.

If the new mouse-utf8 option is on, UTF-8 mouse input is enabled for all
UTF-8 terminals. The option defaults to on if LANG etc are set in the
same manner as the utf8 option.

With help and based on code from hsim at gmx.li.
2011-01-07 14:34:45 +00:00
Tiago Cunha
3aaf5b9b1e Sync OpenBSD patchset 827:
Handle a # at the end of a replacement string (such as status-left)
correctly. Found by Thomas Adam.
2011-01-07 14:32:26 +00:00
Nicholas Marriott
b463d3de54 Missing HAVE_STDINT_H. 2011-01-07 00:35:13 +00:00
Nicholas Marriott
f705c0e013 Whoops, bad copy and paste. 2011-01-04 09:48:10 +00:00
Nicholas Marriott
11dcbd7556 Support --enable-static. 2011-01-04 09:43:14 +00:00
Tiago Cunha
03ec2482c9 libevent-2 works now as well. 2011-01-03 23:58:10 +00:00
Tiago Cunha
a2387330ce Zap paths.h include. 2011-01-03 23:55:30 +00:00
Tiago Cunha
3689640b4e Update _SOURCES. 2011-01-03 23:54:51 +00:00
Tiago Cunha
36c7c7537a Sync OpenBSD patchset 826:
Move the user-visible parts of all options (names, types, limit, default
values) together into one set of tables in options-table.c. Also clean
up and simplify cmd-set-options.c and move a common print function into
option-table.c.
2011-01-03 23:52:38 +00:00
Nicholas Marriott
2bdae526ad More indentation tweaking. 2011-01-03 23:43:35 +00:00
Nicholas Marriott
69f6b23945 Include all osdep-*.c in dist. 2011-01-03 23:40:21 +00:00
Tiago Cunha
a0e7facee6 Sync OpenBSD patchset 825:
suspend-client has used -t for the client target (like everything else)
for ages, fix the usage string and man page and trim some leftover code.
2011-01-03 23:33:12 +00:00
Tiago Cunha
a24b67fc5a Sync OpenBSD patchset 824:
Last few tables that should be const.
2011-01-03 23:32:04 +00:00
Tiago Cunha
521247bedb Sync OpenBSD patchset 823:
Sprinkle a little more const.
2011-01-03 23:31:26 +00:00
Tiago Cunha
9ad028e8ee Sync OpenBSD patchset 822:
Another table that should be const.
2011-01-03 23:30:43 +00:00
Tiago Cunha
d9c848d3a6 Sync OpenBSD patchset 821:
Key table should be const.
2011-01-03 23:29:49 +00:00
Tiago Cunha
66fb24c3a5 Sync OpenBSD patchset 820:
Add a -P option to new-window and split-window to print the new window
or pane index in target form (useful to pass it into other commands).
2011-01-03 23:29:09 +00:00
Tiago Cunha
d3c04b74ec Sync OpenBSD patchset 819:
Don't reset the activity timer for unattached sessions every second,
this screws up the choice of most-recently-used. Instead, break the time
update into a little function and do it when the session is attached.

Pointed out by joshe@.
2011-01-03 23:27:54 +00:00
Tiago Cunha
09ef2c9f40 Sync OpenBSD patchset 818:
Remove unused variable.
2011-01-03 23:26:14 +00:00
Nicholas Marriott
edc298d0a1 Wrap long line differently. 2011-01-02 15:49:31 +00:00
Nicholas Marriott
703baa8769 Fail if no libevent or curses, from Thomas Adam. 2011-01-02 15:45:43 +00:00
Nicholas Marriott
0d77e5e959 Make version more prominent. 2011-01-01 13:39:19 +00:00
Nicholas Marriott
c120d09a5e libevent 2 works now as well. 2011-01-01 13:34:57 +00:00
Nicholas Marriott
3a0d40b84d Add. 2011-01-01 05:09:11 +00:00
Nicholas Marriott
234211a6f6 Add. 2011-01-01 05:01:54 +00:00
Nicholas Marriott
7ecbc18d5d Also done. 2011-01-01 02:00:50 +00:00
Nicholas Marriott
dc7fb15251 Remove some done or duplicates, reorder. 2011-01-01 01:59:03 +00:00
Nicholas Marriott
ce79d6081f And moar. 2010-12-31 22:33:44 +00:00
Nicholas Marriott
d5a63c21b4 Make indentation better. 2010-12-31 22:31:45 +00:00
Nicholas Marriott
b066ad0fd8 Default enable-debug to on in CVS (can be changed for releases). 2010-12-31 22:18:35 +00:00
Nicholas Marriott
620b59e843 RCS $Id$. 2010-12-31 22:13:48 +00:00
Nicholas Marriott
f71b3054cd Switch tmux to use autoconf and automake.
Although they suck, they suck less than the alternatives.
2010-12-31 22:12:33 +00:00
Tiago Cunha
60dd440082 Sync OpenBSD patchset 817:
fix trailing whitespace;
2010-12-31 02:00:30 +00:00
Tiago Cunha
f72f21951c Sync OpenBSD patchset 816:
Remove some unused defines.
2010-12-31 01:59:47 +00:00
Tiago Cunha
67b333ec84 Sync OpenBSD patchset 815:
Fix BUFFERS section now they are global.
2010-12-31 01:58:27 +00:00
Nicholas Marriott
b9f36cc226 +. 2010-12-31 01:39:50 +00:00
Tiago Cunha
bbf44d6ff3 Done. 2010-12-30 23:15:34 +00:00
Tiago Cunha
9ebee6aef8 Global paste buffers instead of per-session which renders copy-buffer useless.
As a consequence buffer-limit is now a server option.
2010-12-30 22:39:49 +00:00
Tiago Cunha
095e1b410a Sync OpenBSD patchset 812:
Support all four of the xterm mouse modes. Based on a diff from hsim at
gmx.li.
2010-12-30 22:27:38 +00:00
Tiago Cunha
210b4553a5 Sync OpenBSD patchset 811:
Allow the config file parser and source-file to return "don't exit" to
the client to let attach work from configuration files.
2010-12-30 22:26:07 +00:00
Nicholas Marriott
e0ad1e5706 Stray blank line. 2010-12-30 20:42:39 +00:00
Nicholas Marriott
436f3b357e epoll on Linux is broken with /dev/null so it needs to be disabled.
Instead of adding another BROKEN_* define, move event_init into
osdep-*.c.
2010-12-30 20:41:08 +00:00
Tiago Cunha
ba89a048ed Working on 1.5. 2010-12-27 22:13:35 +00:00
Tiago Cunha
dcef4f8084 Major changes since the previous version. 2010-12-27 21:37:42 +00:00
Tiago Cunha
030d284006 No point in talking about this here when it's already covered by other files. 2010-12-27 21:36:37 +00:00
Tiago Cunha
1b037f74f4 Bump VERSION and comment FDEBUG. 2010-12-27 21:32:16 +00:00
Tiago Cunha
750e6ad542 usage output should fit on a 80 column display. 2010-12-27 21:22:24 +00:00
Tiago Cunha
5f72510edf Sync OpenBSD patchset 810:
tweak previous;
2010-12-27 21:17:25 +00:00
Tiago Cunha
5d86284a1a Sync OpenBSD patchset 809:
Add a missing .Pp and sort options alphabetically, from Tiago Cunha.
2010-12-27 21:13:59 +00:00
Tiago Cunha
3cd9ea1789 Sync OpenBSD patchset 808:
server_kill_window can modify the RB tree so don't use RB_FOREACH, fixes
crash seen by Dan Harnett.
2010-12-25 23:44:37 +00:00
Tiago Cunha
3585feca54 Sync OpenBSD patchset 807:
Style tweaks.
2010-12-25 23:43:53 +00:00
Tiago Cunha
a373235106 Sync OpenBSD patchset 806:
Store sessions in an RB tree by name rather than a list, this is tidier
and allows them to easily be shown sorted in various lists
(list-sessions/choose-sessions).

Keep a session index which is used in a couple of places internally but
make it an ever-increasing number rather than filling in gaps with new
sessions.
2010-12-22 15:36:44 +00:00
Tiago Cunha
9f3399da00 Sync OpenBSD patchset 805:
Fix another stray addition that was too early. Oops.
2010-12-22 15:33:14 +00:00
Tiago Cunha
c05a47ad0d Sync OpenBSD patchset 804:
Undo a change to next/previous session that got mixed in prematurely.
2010-12-22 15:32:40 +00:00
Tiago Cunha
a932742a8a Sync OpenBSD patchset 803:
Dead sessions are never on the active sessions list, so the SESSION_DEAD
flag is effectively unused. Remove it.
2010-12-22 15:31:56 +00:00
Tiago Cunha
bb728b89a7 Sync OpenBSD patchset 802:
Use pointer rather than index for the client's last session.
2010-12-22 15:31:00 +00:00
Tiago Cunha
64d16cf2d6 Sync OpenBSD patchset 801:
Unify the way sessions are used by callbacks - store the address and use
the reference count, then check it is still on the global sessions list
in the callback.
2010-12-22 15:28:51 +00:00
Tiago Cunha
b8eae3902b Sync OpenBSD patchset 800:
Don't nuke the index counter when a session group comes up.
2010-12-22 15:25:07 +00:00
Tiago Cunha
d1bdc9a161 Sync OpenBSD patchset 799:
Add other-pane-height and other-pane-width options, allowing the width
or height of the smaller panes in the main-horizontal and main-vertical
layouts to be set. Mostly from David Goodlad.
2010-12-22 15:23:59 +00:00
Nicholas Marriott
cd92f44686 "So you have screwed up your /dev/null?" From Mathias Gumz. 2010-12-15 23:31:30 +00:00
Nicholas Marriott
206ae727f9 Read ${X} environment variables in strings and $HOME from the global
environment rather than getenv, this allows them to be updated during
the configuration file.
2010-12-13 22:53:56 +00:00
Nicholas Marriott
5fcd6711e4 Track the last session for a client and add a flag to switch-client and
a key binding (L) to move a client back to its last session.
2010-12-11 18:42:20 +00:00
Nicholas Marriott
d227a2e661 Remove a bunch of stuff that is done a few that aren't going to happen
and remove the priority list for now.
2010-12-11 18:06:42 +00:00
Nicholas Marriott
0b8ce56d73 Fix rectangle copy to behave like emacs - the cursor is not part of the
selection on the right edge but on the left it is.
2010-12-11 17:57:28 +00:00
Nicholas Marriott
095ffe9cd1 Make the prompt history global for all clients which is much more useful
than per-client history.
2010-12-11 16:15:02 +00:00
Nicholas Marriott
1a4d78c7af -V to report version, SF issue 3038862. 2010-12-10 21:19:13 +00:00
Nicholas Marriott
286fef9b4d Rephrase a confusing sentence. 2010-12-10 21:05:22 +00:00
Nicholas Marriott
1891f1ce99 Some do still need -lrt. 2010-12-08 19:55:31 +00:00
Micah Cowan
3ab25ac5b5 In the built-in layouts, distribute the panes more evenly.
Set the default value of main-pane-width to 80, rather than 81.
2010-12-07 20:23:21 +00:00
Nicholas Marriott
3a4f765a51 Add an option to alert (monitor) for silence (lack of activity) in a
window. From Thomas Adam.
2010-12-06 22:52:21 +00:00
Nicholas Marriott
d0adcbc98a PatchSet 790
Date: 2010/11/29 19:45:58
Author: nicm
Branch: HEAD
Tag: (none)
Log:
If VISUAL or EDITOR contains "vi", configure mode-keys and status-keys
to vi.

Based on a diff from martynas@, previously requested by a couple of
other people.

Members:
        tmux.1:1.190->1.191
        tmux.c:1.93->1.94
2010-12-06 21:59:42 +00:00
Nicholas Marriott
e75187310d PatchSet 789
Date: 2010/11/22 21:13:13
Author: nicm
Branch: HEAD
Tag: (none)
Log:
There is somewhere that WINDOW_HIDDEN is getting set when it shouldn't
be and I can't find it, but the flag itself is a useless optimisation
that only applies to automatic-resize windows, so just dispose of it
entirely.

Fixes problems reported by Nicholas Riley.

Members:
        resize.c:1.5->1.6
        tmux.h:1.246->1.247
        tty.c:1.92->1.93
2010-12-06 21:57:56 +00:00
Nicholas Marriott
7a0468c95c PatchSet 788
Date: 2010/11/15 06:52:11
Author: nicm
Branch: HEAD
Tag: (none)
Log:
Show more window and pane flags in list-* output, and put layout on the
same line.

Members:
        cmd-list-panes.c:1.5->1.6
        cmd-list-windows.c:1.9->1.10
2010-12-06 21:56:32 +00:00
Nicholas Marriott
1b0d235e3a PatchSet 787
Date: 2010/11/14 09:04:22
Author: nicm
Branch: HEAD
Tag: (none)
Log:
Update man page for update-environment.

Members:
        tmux.1:1.189->1.190
2010-12-06 21:55:42 +00:00
Nicholas Marriott
36e537bcef PatchSet 786
Date: 2010/11/14 08:58:25
Author: nicm
Branch: HEAD
Tag: (none)
Log:
Don't allow last and active window to become the same - a very bad move
when the active window is closed and freed. Reported by sthen@.

Members:
        window.c:1.58->1.59
2010-12-06 21:53:50 +00:00
Nicholas Marriott
fd51bf61c9 Add XAUTHORITY to update-environment, requested by Andreas Kloeckner. 2010-12-06 21:53:00 +00:00
Nicholas Marriott
fe4f760eba PatchSet 784
Date: 2010/11/11 20:54:06
Author: nicm
Branch: HEAD
Tag: (none)
Log:
Flag to flush all key bindings from Rob Paisley.

Members:
        cmd-unbind-key.c:1.7->1.8
        tmux.1:1.188->1.189
2010-12-06 21:51:02 +00:00
Nicholas Marriott
3a4b82d27a PatchSet 783
Date: 2010/11/11 20:51:30
Author: nicm
Branch: HEAD
Tag: (none)
Log:
Declaration in header should be extern.

Members:
        tmux.h:1.245->1.246
2010-12-06 21:50:24 +00:00
Nicholas Marriott
ccdafdabca PatchSet 782
Date: 2010/11/01 20:59:45
Author: nicm
Branch: HEAD
Tag: (none)
Log:
Typo, from Rob Paisley.

Members:
        tmux.1:1.187->1.188
2010-12-06 21:49:57 +00:00
Nicholas Marriott
39e277be3c |---------------------
|PatchSet 781
|Date: 2010/10/29 21:11:57
|Author: nicm
|Branch: HEAD
|Tag: (none)
|Log:
|We now send argv to the server after parsing it in the client to get the
|command, so the client should not modify it. Instead, take a copy. Fixes
|parsing command lists, reported by mcbride@.
|
|Members:
|       cmd-list.c:1.5->1.6
|       cmd.c:1.45->1.46
|       tmux.h:1.244->1.245
2010-12-06 21:48:56 +00:00
Nicholas Marriott
1650155589 Another. 2010-12-06 17:10:42 +00:00
Nicholas Marriott
42327f06df And moar. 2010-12-06 17:09:00 +00:00
Nicholas Marriott
1585b1e928 Moar. 2010-12-06 17:05:31 +00:00
Nicholas Marriott
9ab191b053 + SF requests. 2010-12-06 17:03:22 +00:00
Nicholas Marriott
13032d1d88 Using working directory always, from Vivien Mallet. 2010-12-06 17:00:34 +00:00
Nicholas Marriott
64387d18dd +. 2010-12-04 15:28:14 +00:00
Nicholas Marriott
25bf0faf21 +. 2010-11-22 22:29:30 +00:00
Nicholas Marriott
112fc58e6e +. 2010-11-15 20:34:38 +00:00
Nicholas Marriott
ba68bed10e +. 2010-11-13 16:55:30 +00:00
Nicholas Marriott
30e8ed393e Whoops, get the logic the right way round. 2010-11-13 16:29:05 +00:00
Nicholas Marriott
a6fc49ae08 Fix AIX warnings. 2010-11-11 20:45:49 +00:00
Nicholas Marriott
94c2adf499 malloc(0) may return NULL, so only assume that is an error if allocating
more than zero.
2010-11-11 20:41:08 +00:00
Nicholas Marriott
9c541e42f0 AIX doesn't have daemon(). 2010-11-11 20:37:53 +00:00
Nicholas Marriott
96601ce9fe Bring back fuzz.c. 2010-11-02 20:55:13 +00:00
Nicholas Marriott
1cec111af3 >4 now. 2010-11-01 21:42:20 +00:00
Nicholas Marriott
ae7a7be819 I am almost certain we don't need crypt or rt now, and it builds fine on
Linux without.
2010-10-27 21:40:03 +00:00
Nicholas Marriott
58684ea998 And more. 2010-10-27 21:34:59 +00:00
Nicholas Marriott
914f8584ef Style tweaks. 2010-10-27 21:33:15 +00:00
Nicholas Marriott
2287ec7b3e Compat for closefrom(). 2010-10-27 20:21:01 +00:00
Nicholas Marriott
8f84217023 Put setproctitle back under HAVE_SETPROCTITLE. 2010-10-24 19:54:41 +00:00
Tiago Cunha
83447580b1 Remove redundant preprocessor check (it's already taken care of by tmux.h). 2010-10-24 01:55:21 +00:00
Tiago Cunha
1cd9ff4460 Ugh. Don't know how this happened, but make it compile by removing duplicate
code.
2010-10-24 01:51:34 +00:00
Tiago Cunha
cd079e8fbf Sync OpenBSD patchset 780:
Add a last-pane command (bound to ; by default). Requested ages ago by
somebody whose name I have forgotten.
2010-10-24 01:34:30 +00:00
Tiago Cunha
8703e9f2f9 Sync OpenBSD patchset 779:
When removing a pane, don't change the active pane unless the active
pane is actually the one being removed.
2010-10-24 01:32:35 +00:00
Tiago Cunha
2da0730f78 Sync OpenBSD patchset 778:
Mark repeating keys with "(repeat)" in the key list.
2010-10-24 01:31:57 +00:00
Tiago Cunha
bdbd4e28c2 Sync OpenBSD patchset 777:
Merge the before and after attach client code into one in client.c
(instead of two in tmux.c and client.c).
2010-10-24 01:31:08 +00:00
Tiago Cunha
1276ea3653 Zap paths.h compat include. 2010-10-24 00:50:11 +00:00
Tiago Cunha
f79b467dce Sync OpenBSD patchset 776:
Make stdio blocking again before calling shell command with -c.
2010-10-24 00:47:46 +00:00
Tiago Cunha
d4b58c71a2 Sync OpenBSD patchset 775:
Trying to set FD_CLOEXEC on every fd is a lost cause, just use
closefrom() before exec.
2010-10-24 00:45:57 +00:00
Tiago Cunha
5fb4f8c1fa Helper script which greps for compat includes that shouldn't be present in all files but compat.h. 2010-10-24 00:42:04 +00:00
Tiago Cunha
5a0ecc5931 Sync OpenBSD patchset 774:
Fall back on normal session choice method if $TMUX exists but is invalid
rather than rejecting.
2010-10-24 00:32:35 +00:00
Tiago Cunha
e7a4b68f73 Sync OpenBSD patchset 773:
Use an explicit event rather than event_once for the main event so it
can be removed when the client becomes ready.
2010-10-24 00:31:57 +00:00
Tiago Cunha
a7e5092bd4 Sync OpenBSD patchset 772:
Treat the meta bit in the xterm extended modifier key set as the same as
escape (tmux's meta). From Emanuele Giaquinta.
2010-10-24 00:30:51 +00:00
Tiago Cunha
b73ac822fb Sync OpenBSD patchset 771:
Put "or" on new line from command with .Ic.
2010-10-24 00:29:57 +00:00
Nicholas Marriott
0ad532d9c2 Rewrite the screen vs tmux bit to be more accurate and complete and less
subjective.
2010-10-23 14:09:29 +00:00
Nicholas Marriott
b0ad6e94bb +ttyfast. 2010-10-18 19:01:07 +00:00
Tiago Cunha
b2ae7c6261 Sync OpenBSD patchset 770:
Set cause when failing due to linking a window to itself, from Martin
Pieuchot.
2010-10-09 14:31:50 +00:00
Tiago Cunha
6c9269baa7 Sync OpenBSD patchset 769:
Skip NULL entries in the sessions list when choosing the next session,
from Simon Olofsson.
2010-10-09 14:31:14 +00:00
Tiago Cunha
45784bd5d6 Sync OpenBSD patchset 767:
Nuke a leftover RB tree declaration spotted by blambert.
2010-10-09 14:30:26 +00:00
Tiago Cunha
b5349ab5d9 Sync OpenBSD patchset 766:
Two new options:

- server option "exit-unattached" makes the server exit when no clients
  are attached, even if sessions are present;

- session option "destroy-unattached" destroys a session once no clients
  are attached to it.

These are useful for preventing tmux remaining in the background where
it is undesirable and when using tmux as a login shell to keep a limit
on new sessions.
2010-10-09 14:29:32 +00:00
Tiago Cunha
7874b00d4c Sync OpenBSD patchset 765:
Modify the permissions on the socket when adding or removing +x to show
attached sessions, rather than replacing them.
2010-10-09 14:26:29 +00:00
Tiago Cunha
6139fac10d Sync OpenBSD patchset 764:
detach-on-destroy is a session option, not server.
2010-10-09 14:25:40 +00:00
Nicholas Marriott
d0d98d4ec0 done 2010-09-25 20:21:51 +00:00
Tiago Cunha
29f04400b5 Sync OpenBSD patchset 763:
Ugh. Pass the right type into tty_term_has. Teaches me to make last
minute changes :-/.
2010-09-18 15:45:03 +00:00
Tiago Cunha
5126037ea0 Sync OpenBSD patchset 762:
Use UTF-8 line drawing characters on UTF-8 terminals. Fixes some stupid
terminals (I'm looking at you, putty) which disable the vt100 ACS mode
switching sequences in UTF-8 mode.

Also on terminals without ACS at all, use ASCII equivalents where
obvious.
2010-09-18 15:43:53 +00:00
Tiago Cunha
d7a3fc3df4 Sync OpenBSD patchset 761:
Ignore terminal overrides settings without a value.
2010-09-18 15:41:50 +00:00
Tiago Cunha
59dc08a7a0 Sync OpenBSD patchset 760:
When resizing the copy mode screen, don't allow it to end up with the
viewable position beyond the size of the history.
2010-09-18 15:41:18 +00:00
Nicholas Marriott
fe3621cbc5 Update, from Daniel Thau. 2010-09-18 09:36:15 +00:00
Tiago Cunha
89c07dedd9 Sync OpenBSD patchset 759:
Add -n and -p flags to switch-client to move to the next and previous
session (yes, it doesn't match window/pane, but so what, nor does
switch-client).

Based on a diff long ago from "edsouza".
2010-09-10 13:36:17 +00:00
Tiago Cunha
28a0b6fd20 Sync OpenBSD patchset 758:
Do not crash if the screen size is too small for the indicator in copy mode.
2010-09-10 13:34:12 +00:00
Nicholas Marriott
f54482a461 Solaris 9 has no stdint.h, ugh. Reported by a couple of people most
recently Timothy Larson.
2010-09-07 19:32:58 +00:00
Tiago Cunha
afcc29a51d Sync OpenBSD patchset 757:
Simplify xterm modifier detection by treating as a bitmask + 1. Spotted
by and diff from Emanuele Giaquinta.
2010-09-07 13:21:18 +00:00
Tiago Cunha
33df467d40 Sync OpenBSD patchset 756:
Reset running jobs when the status line is enabled or disabled as well,
some people have it bound to a key.
2010-09-07 13:20:28 +00:00
Tiago Cunha
510b43569f Sync OpenBSD patchset 755:
Add missing prototype.
2010-09-07 13:19:53 +00:00
Nicholas Marriott
a8b22d3673 +. 2010-09-01 20:39:32 +00:00
Nicholas Marriott
19923625d4 +. 2010-09-01 20:37:20 +00:00
Nicholas Marriott
3b4d26d16b +. 2010-08-31 22:44:01 +00:00
Tiago Cunha
01052ca38e Sync OpenBSD patchset 754:
When destroying a pane, reset any mode (which reenables pane
bufferevent) before freeing the bufferevent.
2010-08-29 14:46:13 +00:00
Tiago Cunha
ee44a8dca9 Sync OpenBSD patchset 753:
Can't call event_del() without event_set() first - so call event_set()
when setting up the client.
2010-08-29 14:44:55 +00:00
Tiago Cunha
89acd757d0 Sync OpenBSD patchset 752:
MSG_EXIT can now have a return code in the message, so check for that
size as well. Stops the client fatal()ing on exit.
2010-08-29 14:43:45 +00:00
Tiago Cunha
56040be346 Sync OpenBSD patchset 751:
Do not call event_del() for signals after fork(), just use sigaction()
directly instead - calling libevent functions after fork() w/o
event_reinit() is a bad idea, even if in this case it was harmless.
2010-08-29 14:42:11 +00:00
Tiago Cunha
e6bb3d6942 Sync OpenBSD patchset 750:
Do not need to dup() the tty fd sent from the client because it is
already dup()d again later. Fixes a leak seen by espie@.
2010-08-29 14:39:45 +00:00
Nicholas Marriott
aba555509e +-. 2010-08-19 18:04:56 +00:00
Tiago Cunha
c50c4ec834 Sync OpenBSD patchset 749:
Do not allow duplicate session names to be created, reported by Dominik
Honnef, patch from Thomas Adam.
2010-08-11 22:19:03 +00:00
Tiago Cunha
9858071dd0 Sync OpenBSD patchset 748:
Handle failure to change mode, to avoid dying when switching into copy
mode when already in a different mode. Reported by "Florian".
2010-08-11 22:18:28 +00:00
Tiago Cunha
b0169d9b84 Sync OpenBSD patchset 747:
Usage string fixes from Ben Boeckel.
2010-08-11 22:17:32 +00:00
Tiago Cunha
e34c6e2305 Sync OpenBSD patchset 746:
Treat trying to link or move to the same window as an error to avoid
removing it accidentally.
2010-08-11 22:16:43 +00:00
Tiago Cunha
761bd3c9e3 Sync OpenBSD patchset 745:
Change the way backoff works. Instead of stopping reading from the pty
when the client tty backs up too much, just stop updating the tty and
only update the internal screen. Then when the tty recovers, force a
redraw.

This prevents a dodgy client from causing other clients to go into
backoff while still allowing tmux to be responsive (locally) when seeing
lots of output.
2010-08-11 22:16:04 +00:00
Tiago Cunha
5e9429e2d6 Sync OpenBSD patchset 744:
Show which pane is active in the list-panes output, suggested by Dominik
Honnef.
2010-08-11 22:14:23 +00:00
Tiago Cunha
4387db506f Sync OpenBSD patchset 742:
dup() the stdin fd so it isn't closed twice (once for stdin, once for tty).
2010-08-09 21:45:37 +00:00
Tiago Cunha
d7bae0edce Sync OpenBSD patchset 741:
When changing so that the client passes its stdout and stderr as well as
stdin up to the server, I forgot one essential point - the tmux server
could now be both the producer and consumer. This happens when tmux is
run inside tmux, as well as when piping tmux commands together.

So, using stdio(3) was a bad idea - if sufficient data was written, this
could block in write(2). When that happened and the server was both
producer and consumer, it deadlocks.

Change to use libevent bufferevents for the client stdin, stdout and
stderr instead. This is trivial enough for output but requires a
callback mechanism to trigger when stdin is finished.

This relies on the underlying polling mechanism for libevent to work
with whatever devices to which the user could redirect stdin, stdout or
stderr, hence the change to use poll(2) over kqueue(2) for tmux.
2010-08-09 21:44:25 +00:00
Nicholas Marriott
482bd7b65e Basic GNU bash completion from Frank Barknecht. 2010-08-09 18:22:33 +00:00
Nicholas Marriott
f42364b4b5 How to blank on lock, from Thomas Adam, slightly tweaked by me. 2010-07-31 11:46:28 +00:00
Nicholas Marriott
5be8175b0b No more up-pane/down-pane. 2010-07-31 11:39:13 +00:00
Tiago Cunha
5576fe42b2 Sync with reality, per SF bug #3035214. 2010-07-27 18:29:07 +00:00
Micah Cowan
1944747759 Don't enable/disable invalid event pointers. Fixes SF #3033119. 2010-07-22 19:51:48 +00:00
Tiago Cunha
28c4c86589 Sync OpenBSD patchset 738:
Don't return if in the current window since we may want to report a bell
(if bell-action any/current), just clear the flag so the status line
doesn't show the bell.
2010-07-20 17:36:41 +00:00
Tiago Cunha
7ed9b0f8fb Sync OpenBSD patchset 737:
Send the \n to stdout with the message, not stderr... doh.
2010-07-20 17:36:03 +00:00
Nicholas Marriott
11497af4dd Solaris has MAXHOSTNAMELEN in netdb.h. 2010-07-19 18:31:42 +00:00
Tiago Cunha
b0878774e0 Don't hard-code the username. 2010-07-19 13:57:22 +00:00
Tiago Cunha
e71f0842ce Working on 1.4. 2010-07-18 14:53:27 +00:00
Tiago Cunha
9b47a48393 Changes for 1.3. 2010-07-18 13:40:59 +00:00
Tiago Cunha
0482983d53 Done. 2010-07-18 13:39:02 +00:00
Tiago Cunha
2b512dc49d Bump VERSION, and comment FDEBUG. 2010-07-18 13:36:52 +00:00
Tiago Cunha
ae45c2ea45 Sync OpenBSD patchset 736:
some escapes i missed;
2010-07-17 14:39:01 +00:00
Tiago Cunha
11f81e8134 Sync OpenBSD patchset 735:
Make pane/window wrapping more logical (so with 10 windows, +10 from
window 5 stays in the same place), and tidy the code. From Tiago Cunha.
2010-07-17 14:38:13 +00:00
Tiago Cunha
ad6a528f61 Sync OpenBSD patchset 734:
Return the command client return code with MSG_EXIT now that MSG_ERROR and
MSG_PRINT are unused.

New clients should be compatible with old tmux servers but vice versa may print
an error.
2010-07-17 14:36:41 +00:00
Tiago Cunha
46f27eab22 Sync OpenBSD patchset 733:
replace some magic mouse constants with defines for clarity. ok nicm
2010-07-02 02:56:07 +00:00
Tiago Cunha
e4703bacb5 Sync OpenBSD patchset 732:
Custom layouts. list-windows command displays the layout as a string (such as
"bb62,159x48,0,0{79x48,0,0,79x48,80,0}") and it can be applied to another
window (with the same number of panes or fewer) using select-layout.
2010-07-02 02:54:52 +00:00
Tiago Cunha
e4573de97b Sync OpenBSD patchset 731:
Send all three of stdin, stdout, stderr from the client to the server, so that
commands can directly make use of them. This means that load-buffer and
save-buffer can have "-" as the file to read from stdin or write to stdout.

This is a protocol version bump so the tmux server will need to be restarted
after upgrade (or an older client used).
2010-07-02 02:52:13 +00:00
Tiago Cunha
63e76b555d Sync OpenBSD patchset 730:
Store the current working directory in the session, change the default-path
option to default to empty and make that mean that the stored session CWD is
used.
2010-07-02 02:49:19 +00:00
Tiago Cunha
13e7f060b1 Update. 2010-07-02 02:46:39 +00:00
Tiago Cunha
fa34c76275 Sync OpenBSD patchset 729:
New option, detach-on-destroy, to set what happens to a client when the session
it is attached to is destroyed. If on (the default), it is detached; if off, it
is switched to the most recently active session.
2010-07-02 02:45:52 +00:00
Tiago Cunha
985cd3a4de Sync OpenBSD patchset 728:
Use server_destroy_session() for kill-session.
2010-07-02 02:43:50 +00:00
Tiago Cunha
03c1c1cd9f Sync OpenBSD patchset 727:
Setting the cmdlist pointer in the bind-key to NULL to prevent it being freed
after the command is executing is bogus because it may still be needed if the
same command is going to be executed again (for example if you "bind-key a
bind-key b ..."). Making a copy is hard, so instead add a reference count to
the cmd_list.

While here, also print bind-key -n and the rest of the flags properly.

Fixes problem reported by mcbride@.
2010-07-02 02:43:01 +00:00
Tiago Cunha
0e70c8801c Update. 2010-06-22 23:37:28 +00:00
Tiago Cunha
617386370b Nuke vis.h. 2010-06-22 23:36:54 +00:00
Tiago Cunha
bf1e237410 Sync OpenBSD patchset 726:
Add a choose-buffer command for easier use of the paste buffer stack.
2010-06-22 23:35:20 +00:00
Tiago Cunha
8d3b726396 Sync OpenBSD patchset 725:
Extend the -t:+ and -t:- window targets for next and previous window to
accept an offset such as -t:+2. From Tiago Cunha.
2010-06-22 23:29:05 +00:00
Tiago Cunha
47b335dee7 Sync OpenBSD patchset 724:
Having a list of winlinks->alerts for each session is stupid, just store
the alert flags directly in the winlink itself.
2010-06-22 23:26:18 +00:00
Tiago Cunha
6c76724201 Sync OpenBSD patchset 723:
Rename activity->alert in a couple of functions for consistency.
2010-06-22 23:22:31 +00:00
Tiago Cunha
29434cb043 Sync OpenBSD patchset 722:
Give tmux sockets (but not the containing folder) group
permissions. This allows hardlinks to the sockets to be used more
easily.
2010-06-22 23:21:39 +00:00
Nicholas Marriott
b7454e37cb Done. 2010-06-21 00:19:44 +00:00
Nicholas Marriott
e2a5e02022 +. 2010-06-21 00:13:13 +00:00
Micah Cowan
cac532c3d1 Ensure we overwrite wide characters properly, and never overwrite characters we weren't overlapping.
Fixes "disappearing wide characters" glitch.
2010-06-16 18:09:23 +00:00
Tiago Cunha
e186450788 Sync OpenBSD patchset 720:
Last change erroneously used the target argument for looking up the
client which caused pipe-pane to fail when used from the command
line. Instead pass NULL which should use the current client.

Spotted by Tiago Cunha.
2010-06-15 20:25:40 +00:00
Tiago Cunha
3e8092709c Sync OpenBSD patchset 719:
Add a missing command and some missing Ic, from Tiago Cunha.
2010-06-15 20:24:52 +00:00
Nicholas Marriott
1b77ae2684 +. 2010-06-13 11:28:26 +00:00
Tiago Cunha
60134cebda imsg was moved into libutil on OpenBSD. 2010-06-06 13:00:47 +00:00
Tiago Cunha
f34861bad4 Sync OpenBSD patchset 717:
Couple of missing command aliases/flags, from Tiago Cunha.
2010-06-06 00:31:32 +00:00
Tiago Cunha
6503207185 Sync OpenBSD patchset 716:
Fix problems with window sizing seen by Raghavendra D Prabhu when
starting tmux from .xinitrc.

One of the very few things the server relies on the client for now is to
pass through a message on SIGWINCH, but there is a condition where
potentially a SIGWINCH may be lost during the transition from unattached
(main.c) to attached (client.c). So trigger a size change immediately
after the client installs its SIGWINCH handler.

Also, when the terminal is resized, reset the scroll region and cursor
position. Previously, we were clearing our saved idea of these, but in
fact some terminals do not reset them on resize, so this caused problems
during redraw.

While here make a resize to the same size not cause a redraw and rename
the tmux.out output log file to include the tmux PID.
2010-06-06 00:30:34 +00:00
Tiago Cunha
3bba401609 Sync OpenBSD patchset 715:
Support the status_replace # replacement sequences in the pipe-pane
command, thanks to Andrea Barisani.
2010-06-06 00:28:00 +00:00
Tiago Cunha
31657820bc Sync OpenBSD patchset 714:
Shut up gcc4 warnings.
2010-06-06 00:27:08 +00:00
Tiago Cunha
be3643fba0 Sync OpenBSD patchset 713:
This ioctl(TIOCGWINSZ) call is no longer necessary, the result is never
used and the server now does it later on the tty fd directly.
2010-06-06 00:25:47 +00:00
Tiago Cunha
f62d3d22bb Sync OpenBSD patchset 710:
When the mode-mouse option is on, support dragging to make a selection
in copy mode.

Also support the scroll wheel, although xterm strangely does not ignore
it in application mouse mode, causing redraw artifacts when scrolling up
(other terminals appear to be better behaved).
2010-06-06 00:23:44 +00:00
Tiago Cunha
67dc249d0e Sync OpenBSD patchset 709:
Better to say "command key bindings" since we've just called them
command keys.
2010-06-06 00:21:36 +00:00
Tiago Cunha
0778ef230b Sync OpenBSD patchset 708:
There is no real reason not to list all the key bindings here rather
than just a selection.
2010-06-06 00:20:53 +00:00
Tiago Cunha
bebfd7c2c8 Sync OpenBSD patchset 706:
Rename some imsg bits to make namespace collisions less likely buf to
ibuf, buf_read to ibuf_read, READ_BUF_SIZE to IBUF_READ_SIZE.
2010-06-06 00:08:28 +00:00
Tiago Cunha
348c3e69de Sync OpenBSD patchset 705:
Don't die if the client has been detached when the job finishes, just
don't display the output.
2010-06-06 00:04:59 +00:00
Tiago Cunha
0d6a64070c Sync OpenBSD patchset 704:
Fix an out-of-date comment.
2010-06-06 00:04:18 +00:00
Tiago Cunha
bb4d770e45 No vis.h in here. 2010-06-06 00:03:02 +00:00
Tiago Cunha
e55a59eebc Sync OpenBSD patchset 702:
Enhance paste-buffer to allow lines to be separated by any string, from
Andrea Barisani.
2010-06-06 00:01:36 +00:00
Tiago Cunha
11cd05db27 Sync OpenBSD patchset 701:
Colour+attribute options for status line alerts, from Alex Alexander.
2010-06-05 23:56:29 +00:00
Tiago Cunha
6c6255f2d7 Sync OpenBSD patchset 700:
Accept (and document) "none" instead of "default" for attributes as it
is clearer and avoids confusion with default colours.
2010-06-05 23:54:51 +00:00
Micah Cowan
227e458ebb Use a macro-based mask for obtaining a key or modifier-set from the combination.
Display C-@, etc, as C-Space, in list-keys.
2010-06-05 20:29:11 +00:00
Nicholas Marriott
89eb95265a Must allocate for putenv. 2010-06-05 18:20:48 +00:00
Nicholas Marriott
d98efa5378 Only need to build setenv.c once. 2010-06-05 18:14:29 +00:00
Nicholas Marriott
a9c6976268 Should be const char *. 2010-06-05 16:29:40 +00:00
Micah Cowan
d9c99b83c7 Make double start-of-line do what double end-of-line does, on wrapped lines. 2010-06-05 07:48:35 +00:00
Micah Cowan
d27956f160 Allow C-Space to work correctly once again, and forbid nonsensical combinations such as C-Enter or C-Escape. 2010-06-05 06:27:19 +00:00
Nicholas Marriott
e334deb872 +. 2010-05-27 08:29:17 +00:00
Nicholas Marriott
e50dc0745f +. 2010-05-24 18:21:07 +00:00
Micah Cowan
f11f71752a Pass in the session, rather than the client, to window modes' key() function.
We were only ever using the client to find the session anyway.
2010-05-22 21:56:04 +00:00
Nicholas Marriott
9e7a5fa5ef Spacing nits. 2010-05-19 21:49:57 +00:00
Nicholas Marriott
9c01a3d0db Solaris 9 is missing CMSG_ALIGN and some of the RFC2292 CMSG_*. From
Dagobert Michelsen.
2010-05-19 21:40:49 +00:00
Nicholas Marriott
278effd7ea Solaris 9 doesn't have setenv and unsetenv so add compat versions, based
on code from Dagobert Michelsen.
2010-05-19 21:31:39 +00:00
Nicholas Marriott
59c13133de Fix bad merge, from Romain Francoise. 2010-05-16 17:50:31 +00:00
Nicholas Marriott
41afc38dcc +. 2010-05-14 19:05:06 +00:00
Tiago Cunha
0beb31c261 Update. 2010-05-14 14:38:50 +00:00
Tiago Cunha
6694a01861 Sync OpenBSD patchset 698:
Catch SIGHUP and terminate if running as a client. This prevents clients
from being left hanging around when, for example, a SSH session is
disconnected.

ok nicm@
2010-05-14 14:35:26 +00:00
Tiago Cunha
9900e28ba8 Sync OpenBSD patchset 697:
Identical behaviour to select-prompt can now be obtained with
command-prompt, so remove select-prompt and change ' to be bound to
command-prompt -p index "select-window -t :%%".
2010-05-14 14:33:39 +00:00
Tiago Cunha
fc69b9ccb7 Sync OpenBSD patchset 696:
Make signal handler setup/teardown two common functions instead of six,
and reset SIGCHLD after fork to fix problems with some shells. From
Romain Francoise.
2010-05-14 14:30:01 +00:00
Tiago Cunha
d3dd6709bc Sync OpenBSD patchset 693:
Make C-] and other punctuation-based control key combinations work again.

ok nicm
2010-05-14 14:21:07 +00:00
Tiago Cunha
3cded44623 Sync OpenBSD patchset 692:
sort options.
2010-05-14 14:19:41 +00:00
Tiago Cunha
50cad52ae6 Sync OpenBSD patchset 691:
Make the active pane border have a green foreground instead of
background by default.
2010-05-14 14:18:54 +00:00
Tiago Cunha
701b5bdf61 Sync OpenBSD patchset 688:
Add a tiled layout, originally from Liam Bedford a while ago, fixed up
by me.
2010-05-14 14:16:37 +00:00
Nicholas Marriott
4e120c00f7 Use LC_ALL for sed too since apparently some platforms play silly games
in other locales.
2010-05-12 19:47:25 +00:00
Nicholas Marriott
7d4588f470 +. 2010-05-12 19:21:15 +00:00
Nicholas Marriott
893be14cf8 +. 2010-04-28 19:08:40 +00:00
Micah Cowan
342a47bc77 Avoid crashing in copy-mode during resize, when our history-viewing offset is larger than the new total number of history lines. 2010-04-28 14:29:27 +00:00
Nicholas Marriott
18ed37622e When converting A-Z into a control character, want to subtract 64 not
65... whoops.
2010-04-23 20:33:08 +00:00
Nicholas Marriott
ec56ec7920 Use INSTALL so people on Solaris can set it to ginstall. 2010-04-23 07:38:36 +00:00
Nicholas Marriott
0c5a964e63 Support NetBSD 6 which will now have its own terminfo (yay). 2010-04-23 07:29:39 +00:00
Tiago Cunha
c4c542efb9 Sync OpenBSD patchset 686:
Mark zombie windows as dead in choose-window list, from Romain Francoise.
2010-04-22 21:51:27 +00:00
Tiago Cunha
2bc150d16d Sync OpenBSD patchset 685:
Rewrite key string conversions to be readable and to work properly for
multiple modifiers.
2010-04-22 21:50:30 +00:00
Tiago Cunha
7163907ab6 Sync OpenBSD patchset 684:
Catch SIGCHLD to avoid a zombie, from patrick keshishian.
2010-04-22 21:48:49 +00:00
Nicholas Marriott
02fc1fe0da Done. 2010-04-21 21:35:07 +00:00
Nicholas Marriott
8e67b07489 Don't set user and group with install, from Nicolas Pinto. 2010-04-21 21:22:06 +00:00
Tiago Cunha
0ed80637e7 Sync OpenBSD patchset 683:
Fix typo in escape state table leading to fatal() when \033} or \033~
was entered, from Chris Johnsen.
2010-04-18 15:11:47 +00:00
Tiago Cunha
b03418fc6b Sync OpenBSD patchset 682:
If remain-on-exit is set, both the error callback and a SIGCHLD could
destroy the same pane (because the first one doesn't remove it from the
list of panes), causing the pane bufferevent to be freed twice. So don't
free it if the fd has already been set to -1, from Romain Francoise.
2010-04-18 15:10:55 +00:00
Nicholas Marriott
c0f03afbac +. 2010-04-18 07:37:09 +00:00
Tiago Cunha
0646b3caf2 Sync OpenBSD patchset 680:
Remove XXX comment and just close received fd if calloc() fails.

If this happens the imsg may no longer be usable as there may be queued
messages, but this is a) already the case with the code now, and b)
would be the case if recvmsg() fails anyway, so we can document that -1
from imsg_read() invalidates the struct imsgbuf.

discussed with and ok eric
2010-04-12 21:45:18 +00:00
Micah Cowan
b2e752b384 Don't try to use a window-link that may have been freed.
In the case where a join-pane is performed from within a grouped session,
and the source pane had no siblings in the window (causing the window to
be destroyed), there was an invalid access of the destination window
link (which had been destroyed as part of the group session's
resynchronization with the original session, due to killing the
now-empty source window).
CVS: ----------------------------------------------------------------------
CVS: Enter Log.  Lines beginning with `CVS:' are removed automatically
CVS:
CVS: Committing in .
CVS:
CVS: Modified Files:
CVS: 	cmd-join-pane.c
CVS: ----------------------------------------------------------------------
2010-04-09 07:09:37 +00:00
Nicholas Marriott
08632b4f0a there can be only one rpathbuf 2010-04-08 07:54:43 +00:00
Nicholas Marriott
10b73b7a11 Sync nit. 2010-04-06 22:08:10 +00:00
Nicholas Marriott
cd0f22b96e Unbreak. Whoops. 2010-04-06 22:02:52 +00:00
Nicholas Marriott
610056abbe Man page sync. 2010-04-06 22:02:03 +00:00
Nicholas Marriott
3743238a86 From Bob Beck:
rather than using an empty "" as the default window title, put the hostname
of the machine we are running on in there.

makes my many green lines easier to deal with without using fiddly options to
set it.
2010-04-06 22:01:32 +00:00
Nicholas Marriott
531db321e3 -s src-pane. 2010-04-06 21:59:59 +00:00
Nicholas Marriott
642f549e4d Dead assignment. 2010-04-06 21:59:37 +00:00
Nicholas Marriott
0fc65537a3 Run job commands explicitly in the global enviroment (which can be
modified with setenv -g) rather than with the environment tmux started
with.
2010-04-06 21:59:19 +00:00
Nicholas Marriott
091db41bc9 Squash a function that is only called in a callback into the
callback function.
2010-04-06 21:58:33 +00:00
Nicholas Marriott
67300e9524 Stupid style nits. 2010-04-06 21:45:36 +00:00
Nicholas Marriott
f2a4ef5260 window-more.c is now defunct. 2010-04-06 10:53:41 +00:00
Nicholas Marriott
7dc1720522 +. 2010-04-05 22:28:56 +00:00
Nicholas Marriott
07dcf8610f FreeBSD kqueue is broken before 8. 2010-04-05 22:28:25 +00:00
Micah Cowan
2d74ce1d3a Merge output (more) and copy modes into one single mode (called copy). 2010-04-05 05:11:44 +00:00
Nicholas Marriott
5879e2a32b libevent needs librt on Linux, from Aaron Isotton. 2010-04-02 21:26:40 +00:00
Nicholas Marriott
1392fba63d Don't accept keys with modifiers as input. Fixes crash reported by Brian
R Landy.
2010-03-31 18:24:08 +00:00
Nicholas Marriott
1c6ab725f5 +. 2010-03-29 18:54:07 +00:00
Nicholas Marriott
4012917302 Nuke unused functions. 2010-03-27 15:12:56 +00:00
Nicholas Marriott
dd7abd9b4c -a flag to insert a window after an existing one, moving other windows
up as necessary.
2010-03-27 15:12:11 +00:00
Nicholas Marriott
51c776fe93 +. 2010-03-27 13:43:13 +00:00
Nicholas Marriott
9382e546df +. 2010-03-18 21:10:11 +00:00
Nicholas Marriott
659d15786a Reset output functions too when changing client after attaching. 2010-03-18 21:06:40 +00:00
Nicholas Marriott
2307b91ecb paste-buffer should be per pane, from C. Coutinho. 2010-03-18 21:02:41 +00:00
Nicholas Marriott
a2c87eb899 Unused variable. 2010-03-16 23:40:14 +00:00
Nicholas Marriott
33a90efc93 Minor Nazi style tweaks to previous, and man page rephrasery. 2010-03-16 17:51:32 +00:00
Micah Cowan
009d8d2ea7 Jump-forward, jump-backward in copy mode, based on vi's F and f commands. 2010-03-16 17:30:58 +00:00
Nicholas Marriott
aa8f9018ea Support up, down, left, right movement through panes with -UDLR flags to
select-pane.

Also remove up- and down-pane: equivalent behaviour is now available
using -t :.+ and -t :.-.
2010-03-15 22:03:38 +00:00
Nicholas Marriott
4de04fac2c Accept a full key match (not a partial) even if there is data left in
the buffer.
2010-03-15 20:44:51 +00:00
Nicholas Marriott
593bcbdd49 +. 2010-03-15 16:09:49 +00:00
Nicholas Marriott
9f5b9ba0d6 New input parser based on http://vt100.net/emu/dec_ansi_parser. 2010-03-15 12:51:23 +00:00
Nicholas Marriott
b1a3090877 + an item. 2010-03-14 23:46:52 +00:00
Nicholas Marriott
4271320bb7 Quick prioritise for 1.3. 2010-03-14 23:46:09 +00:00
Nicholas Marriott
51eab54102 Avoid use-after-free when cancelling copy mode. 2010-03-14 23:17:59 +00:00
Nicholas Marriott
51c135ed73 +. 2010-03-10 23:32:49 +00:00
Nicholas Marriott
f6d36e60cf Mention dependencies. 2010-03-10 22:13:17 +00:00
Tiago Cunha
38bc7e87c5 Working on 1.3. 2010-03-10 15:44:13 +00:00
194 changed files with 13983 additions and 9329 deletions

224
CHANGES
View File

@@ -1,3 +1,225 @@
CHANGES FROM 1.5 TO 1.6, 23 January 2012
* Extend the mode-mouse option to add a third choice which means the mouse
does not enter copy mode.
* Add a -r flag to switch-client to toggle the client read-only flag.
* Add pane-base-index option.
* Support \ for line continuation in the configuration file.
* Framework for more powerful formatting of command output and use it for
list-{panes,windows,sessions}. This allows more descriptive replacements
(such as #{session_name}) and conditionals.
* Mark dead panes with some text saying they are dead.
* Reject $SHELL if it is not a full path.
* Add -S option to refresh-client to redraw status line.
* Add an else clause for if-shell.
* Try to resolve relative paths for loadb and saveb (first, using client
working directory, if any, then default-path or session working directory).
* Support for \e[3J to clear the history and send the corresponding
terminfo code (E3) before locking.
* When in copy mode, make repeat count indicate buffer to replace, if used.
* Add screen*:XT to terminal-overrides for tmux-in-tmux.
* Status-line message attributes added.
* Move word-separators to be a session rather than window option.
* Change the way the working directory for new processes is discovered. If
default-path isn't empty, it is used. Otherwise, if a new window is created
from the command-line, the working directory of the client is used. If not,
platform specific code is used to retrieve the current working directory
of the process in the active pane. If that fails, the directory where the
session was created is used, instead.
* Do not change the current pane if both mouse-select-{pane,window} are
enabled.
* Add \033[s and \033[u to save and restore cursor position.
* Allow $HOME to be used as default-path.
* Add CNL and CPL escape sequences.
* Calculate last position correctly for UTF-8 wide characters.
* Add an option allow-rename to disable the window rename escape sequence.
* Attributes for each type of status-line alert (ie bell, content and
activity) added. Therefore, remove the superfluous options
window-status-alert-{attr,bg,fg}.
* Add a -R flag to send-keys to reset the terminal.
* Add strings to allow the aixterm bright colours to be used when
configuring colours.
* Drop the ability to have a list of keys in the prefix in favour of two
separate options, prefix and prefix2.
* Flag -2 added to send-prefix to send the secondary prefix key.
* Show pane size in top right of display panes mode.
* Some memory leaks plugged.
* More command-prompt editing improvements.
* Various manpage improvements.
* More Vi mode improvements.
CHANGES FROM 1.4 TO 1.5, 09 July 2011
* Support xterm mouse modes 1002 and 1003.
* Change from a per-session stack of buffers to one global stack. This renders
copy-buffer useless and makes buffer-limit now a server option.
* Fix most-recently-used choice by avoiding reset the activity timer for
unattached sessions every second.
* Add a -P option to new-window and split-window to print the new window or
pane index in target form (useful to pass it into other commands).
* Handle a # at the end of a replacement string (such as status-left)
correctly.
* Support for UTF-8 mouse input (\033[1005h) which was added in xterm 262.
If the new mouse-utf8 option is on, UTF-8 mouse input is enabled for all
UTF-8 terminals. The option defaults to on if LANG etc are set in the same
manner as the utf8 option.
* Support for HP-UX.
* Accept colours of the hex form #ffffff and translate to the nearest from the
xterm(1) 256-colour set.
* Clear the non-blocking IO flag (O_NONBLOCK) on the stdio file descriptors
before closing them (fixes things like "tmux ls && cat").
* Use TMPDIR if set.
* Fix next and previous session functions to actually work.
* Support -x and -y for new-session to specify the initial size of the window
if created detached with -d.
* Make bind-key accept characters with the top-bit-set and print them as octal.
* Set $TMUX without the session when background jobs are run.
* Simplify the way jobs work and drop the persist type, so all jobs are
fire-and-forget.
* Accept tcgetattr/tcsetattr(3) failure, fixes problems with fatal() if the
terminal disappears while locked.
* Add a -P option to detach to HUP the client's parent process (usually causing
it to exit as well).
* Support passing through escape sequences to the underlying terminal by using
DCS with a "tmux;" prefix.
* Prevent tiled producing a corrupt layout when only one column is needed.
* Give each pane created in a tmux server a unique id (starting from 0), put it
in the TMUX_PANE environment variable and accept it as a target.
* Allow a start and end line to be specified for capture-pane which may be
negative to capture part of the history.
* Add -a and -s options to lsp to list all panes in the server or session
respectively. Likewise add -s to lsw.
* Change -t on display-message to be target-pane for the #[A-Z] replacements
and add -c as target-client.
* The attach-session command now prefers the most recently used unattached
session.
* Add -s option to detach-client to detach all clients attached to a session.
* Add -t to list-clients.
* Change window with mouse wheel over status line if mouse-select-window is on.
* When mode-mouse is on, automatically enter copy mode when the mouse is
dragged or the mouse wheel is used. Also exit copy mode when the mouse wheel
is scrolled off the bottom.
* Provide #h character pair for short hostname (no domain).
* Don't use strnvis(3) for the title as it breaks UTF-8.
* Use the tsl and fsl terminfo(5) capabilities to update terminal title and
automatically fill them in on terminals with the XT capability (which means
their title setting is xterm-compatible).
* Add a new option, mouse-resize-pane. When on, panes may be resized by
dragging their borders.
* Fix crash by resetting last pane on {break,swap}-pane across windows.
* Add three new copy-mode commands - select-line, copy-line, copy-end-of-line.
* Support setting the xterm clipboard when copying from copy mode using the
xterm escape sequence for the purpose (if xterm is configured to allow it).
* Support xterm(1) cursor colour change sequences through terminfo(5) Cc
(set) and Cr (reset) extensions.
* Support DECSCUSR sequence to set the cursor style with two new terminfo(5)
extensions, Cs and Csr.
* Make the command-prompt custom prompts recognize the status-left option
character pairs.
* Add a respawn-pane command.
* Add a couple of extra xterm-style keys that gnome terminal provides.
* Allow the initial context on prompts to be set with the new -I option to
command-prompt. Include the current window and session name in the prompt
when renaming and add a new key binding ($) for rename session.
* Option bell-on-alert added to trigger the terminal bell when there is an
alert.
* Change the list-keys format so that it shows the keys using actual tmux
commands which should be able to be directly copied into the config file.
* Show full targets for lsp/lsw -a.
* Make confirm-before prompt customizable with -p option like command-prompt
and add the character pairs #W and #P to the default kill-{pane,window}
prompts.
* Avoid sending data to suspended/locked clients.
* Small memory leaks in error paths plugged.
* Vi mode improvements.
CHANGES FROM 1.3 TO 1.4, 27 December 2010
* Window bell reporting fixed.
* Show which pane is active in the list-panes output.
* Backoff reworked.
* Prevent the server from dying when switching into copy mode when already
in a different mode.
* Reset running jobs when the status line is enabled or disabled.
* Simplify xterm modifier detection.
* Avoid crashing in copy mode if the screen size is too small for the
indicator.
* Flags -n and -p added to switch-client.
* Use UTF-8 line drawing characters on UTF-8 terminals, thus fixing some
terminals (eg putty) which disable the vt100 ACS mode switching sequences
in UTF-8 mode. On terminals without ACS, use ASCII equivalents.
* New server option exit-unattached added.
* New session option destroy-unattached added.
* Fall back on normal session choice method if $TMUX exists but is invalid
rather than rejecting.
* Mark repeating keys with "(repeat)" in the key list.
* When removing a pane, don't change the active pane unless the active pane
is actually the one being removed.
* New command last-pane added.
* AIX fixes.
* Flag -a added to unbind-key.
* Add XAUTHORITY to update-environment.
* More info regarding window and pane flags is now shown in list-*.
* If VISUAL or EDITOR contains "vi" configure mode-keys and status-key to vi.
* New window option monitor-silence and session option visual-silence added.
* In the built-in layouts distribute the panes more evenly.
* Set the default value of main-pane-width to 80 instead of 81.
* Command-line flag -V added.
* Instead of keeping a per-client prompt history make it global.
* Fix rectangle copy to behave like emacs (the cursor is not part of the
selection on the right edge but on the left it is).
* Flag -l added to switch-client.
* Retrieve environment variables from the global environment rather than
getenv(3), thus allowing them to be updated during the configuration file.
* New window options other-pane-{height,width} added.
* More minor bugs fixed and manpage improvements.
CHANGES FROM 1.2 TO 1.3, 18 July 2010
* New input parser.
* Flags to move through panes -UDLR added to select-pane.
* Commands up-pane, and down-pane removed, since equivalent behaviour is now
available through the target flag (-t:+ and -t:-).
* Jump-forward/backward in copy move (based on vi's F, and f commands).
* Make paste-buffer accept a pane as a target.
* Flag -a added to new-window to insert a window after an existing one, moving
windows up if necessary.
* Merge more mode into copy mode.
* Run job commands explicitly in the global environment (which can be modified
with setenv -g), rather than with the environment tmux started with.
* Use the machine's hostname as the default title, instead of an empty string.
* Prevent double free if the window option remain-on-exit is set.
* Key string conversions rewritten.
* Mark zombie windows as dead in the choose-window list.
* Tiled layout added.
* Signal handling reworked.
* Reset SIGCHLD after fork to fix problems with some shells.
* Select-prompt command removed. Therefore, bound ' to command-prompt -p index
"select-window -t:%%" by default.
* Catch SIGHUP and terminate if running as a client, thus avoiding clients from
being left hanging around when, for instance, a SSH session is disconnected.
* Solaris 9 fixes (such as adding compat {get,set}env(3) code).
* Accept none instead of default for attributes.
* Window options window-status-alert-{alert,bg,fg} added.
* Flag -s added to the paste-buffer command to specify a custom separator.
* Allow dragging to make a selection in copy mode if the mode-mouse option is
set.
* Support the mouse scroll wheel.
* Make pipe-pane accept special character sequences (eg #I).
* Fix problems with window sizing when starting tmux from .xinitrc.
* Give tmux sockets (but not the containing folder) group permissions.
* Extend the target flags (ie -t) to accept an offset (for example -t:+2), and
make it wrap windows, and panes.
* New command choose-buffer added.
* New server option detach-on-destroy to set what happens to a client when the
session it is attached to is destroyed. If on (default), the client is
detached. Otherwise, the client is switched to the most recently active of
the remaining sessions.
* The commands load-buffer, and save-buffer now accept a dash (-) as the file
to read from stdin, or write to stdout.
* Custom layouts added.
* Additional code reduction, bug fixes, and manpage enhancements.
CHANGES FROM 1.1 TO 1.2, 10 March 2010 CHANGES FROM 1.1 TO 1.2, 10 March 2010
* Switch to libevent. * Switch to libevent.
@@ -1467,7 +1689,7 @@ The list of older changes is below.
(including mutt, emacs). No status bar yet and no key remapping or other (including mutt, emacs). No status bar yet and no key remapping or other
customisation. customisation.
$Id: CHANGES,v 1.302 2010-03-10 15:18:11 tcunha Exp $ $Id$
LocalWords: showw utf UTF fulvio ciriaco joshe OSC APC gettime abc DEF OA clr LocalWords: showw utf UTF fulvio ciriaco joshe OSC APC gettime abc DEF OA clr
LocalWords: rivo nurges lscm Erdely eol smysession mysession ek dstname RB ms LocalWords: rivo nurges lscm Erdely eol smysession mysession ek dstname RB ms

211
FAQ
View File

@@ -12,29 +12,98 @@ tmux frequently asked questions
* and derivatives. * * and derivatives. *
****************************************************************************** ******************************************************************************
* How is tmux different from GNU screen? What else does it offer? * How is tmux different from GNU screen?
tmux offers several advantages over screen: tmux and GNU screen have many similarities. Some of the main differences I am
aware of are (bearing in mind I haven't used screen for a few years now):
- a clearly-defined client-server model: windows are independent entities which - tmux uses a client-server model. Each server has single Unix domain socket in
may be attached simultaneously to multiple sessions and viewed from multiple /tmp and within one server there are multiple sessions which may be attached
clients (terminals), as well as moved freely between sessions within the same to multiple clients (terminals).
tmux server;
- a consistent, well-documented command interface, with the same syntax
whether used interactively, as a key binding, or from the shell;
- easily scriptable from the shell;
- multiple paste buffers;
- choice of vi or emacs key layouts;
- an option to limit the window size;
- a more usable status line syntax, with the ability to display the first line
of output of a specific command;
- a cleaner, modern, easily extended, BSD-licensed codebase.
There are still a few features screen includes that tmux omits: This has advantages, notably: windows may be linked simultaneously to
multiple sessions; windows may be moved freely between sessions; and a client
may be switched between sessions easily (C-b D). There is one major
disadvantage: if the server crashes, game over, all sessions die. In
practice, however, tmux is quite stable and gets more so as people report any
bugs they hit :-).
- builtin serial and telnet support; this is bloat and is unlikely to be added This model is different from screen, where typically each new screen instance
to tmux; is independent. tmux supports the same behaviour by using multiple servers
- wider platform support, for example IRIX and HP-UX, and for odd terminals. with the -L option but it is not typically recommended.
- Different command interfaces. One of the goals of tmux is that the shell
should be easily usable as a scripting language - almost all tmux commands
can be used from the shell and behave identically whether used from the
shell, from a key binding or from the command prompt. Personally I also find
tmux's command interface much more consistent and clearer, but this is
subjective.
- tmux calls window names (what you see in the status line) "names", screen
calls them "titles".
- tmux has a multiple paste buffers. Not a major one but comes in handy quite a
lot.
- tmux supports automatically renaming windows to the running application
without gross hacks using escape sequences. Its even on by default.
- tmux has a choice of vi or emacs key layouts. Again, not major, but I use
emacs so if tmux did support only one key set it would be emacs and then all
the vi users would get humpy. Key bindings may be completely reconfigured in
any case.
- tmux has an option to limit the window size.
- tmux has search in windows (C-b f).
- The window split (pane) model is different. tmux has two objects, windows and
panes; screen has just windows. This difference has several implications:
* In screen you can have a window appear in several layouts, in tmux a pane
can only be in one window (fixing this is a big todo item but quite
invasive).
* tmux layouts are immutable and do not get changed unless you modify them.
* In tmux, all panes are closed when you kill a window.
* tmux panes do not have individual names, titles and so on.
I think tmux's model is much easier to manage and navigate within a window,
but breaking panes off from and joining them to windows is more clumsy.
tmux also has support for preset pane layouts.
- tmux's status line syntax is more readable and easier to use. I think it'd be
hard for anyone to argue with this. tmux doesn't support running a command
constantly and always using the last line of its output, commands must be run
again each time.
- tmux has modern, easily extended code. Again hard to argue screen is better
if you have looked at the code.
- tmux depends on libevent. I don't see this as a disadvantage: libevent is
small and portable, and on modern systems with current package management
systems dependencies are not an issue. libevent brings advantages in code
simplicity and performance.
- screen allows the window to be bigger than the terminal and can pan around
it. tmux limits the size to the largest attached client. This is a big todo
item for tmux but it is not trivial.
- screen has builtin serial and telnet support; this is bloat and is unlikely
to be added to tmux.
- screen has support for updating utmp. Nobody has really come up with a clean,
portable way to do this without making tmux setuid or setgid yet.
- Environment handling is different.
- tmux tends to be more demanding on the terminal so tends to show up terminal
and application bugs which screen does not.
- screen has wider platform support, for example IRIX, and for odd terminals.
* I found a bug! What do I do? * I found a bug! What do I do?
@@ -167,6 +236,8 @@ the ctrl (bit 5 set, for example ^[[5~ to ^[[5^) modifier in non-xterm(1) mode;
it may be possible to configure vim to accept these, an example of how to do so it may be possible to configure vim to accept these, an example of how to do so
would be welcome. would be welcome.
vim users may also want to set the "ttyfast" option inside tmux.
* Why doesn't elinks set the window title inside tmux? * Why doesn't elinks set the window title inside tmux?
There isn't a way to detect if a terminal supports setting the window title, so There isn't a way to detect if a terminal supports setting the window title, so
@@ -239,4 +310,104 @@ set -g terminal-overrides "xterm*:kLFT5=\eOD:kRIT5=\eOC:kUP5=\eOA:kDN5=\eOB:smkx
Note that this will only work in tmux 1.2 and above. Note that this will only work in tmux 1.2 and above.
$Id: FAQ,v 1.36 2010-02-04 21:01:59 nicm Exp $ * How can I blank the tmux window?
GNU screen has a feature whereby it will blank the screen after a period of
inactivity. To do the same thing in tmux, use the lock-command setting, for
example (with GNU bash):
set -g lock-command 'tput civis && read -s -n1'
This will remove the cursor and tell the shell to quit once a key has been
pressed. For zsh, use "read -s -k1".
In addition, it's possible to have both blanking and locking (for instance via
lock(1) or vlock(1)) by using the following:
bind x set lock-command '/usr/bin/vlock' \; lock-client \; set lock-command 'tput civis && read -s -n1'
* How can I open a new window in the same directory as the current window?
One option is to just run "TMUX= tmux" in the window. However, this only works if no
command is running, so that you can input the command.
A workaround is to let tmux know about the current path through an environment
variable. To do so, use the following command:
[ -n "$TMUX" ] && tmux setenv TMUXPWD_$(tmux display -p "#I") $PWD
Which sets TMUXPWD_i (where i is the number of the current window) to the path
of the current directory. This command can be added to PS1, for example:
PS1='$([ -n "$TMUX" ] && tmux setenv TMUXPWD_$(tmux display -p "#I") $PWD)\h$ '
When a new window is created, the shell should be asked to change
directory. You can define a new binding (for example, if using GNU bash):
bind-key C-c run-shell 'tmux neww "cd $(tmux display -p "\$TMUXPWD_#I"); exec bash"'
This solution will work even if a command is currently running in the terminal,
but it will not work from a window that has just been swapped with another
because TMUXPWD_i will not be updated after a swap. However, once a new prompt
is displayed, TMUXPWD_i is updated properly.
* tmux doesn't start with "daemon failed"
tmux shows something similar to this when started:
fatal: server_start: daemon failed: No such file or directory
fatal: main_dispatch: imsg_read failed
A possible reason is that /dev/null is not a character device or is otherwise
inaccessible.
Check with:
file /dev/null
ls -l /dev/null
If it is not a character device or has incorrect permissions, it can typically
be recreated with:
cd /dev && rm null && ./MAKEDEV null
* vim displays reverse video instead of italics, while less displays italics
(or just regular text) instead of reverse. What's wrong?
Screen's terminfo description lacks italics mode and has standout mode in its
place, but using the same escape sequence that urxvt uses for italics. This
means applications (like vim) looking for italics will not find it and might
turn to reverse in its place, while applications (like less) asking for
standout will end up with italics instead of reverse. To make applications
aware that tmux supports italics and to use a proper escape sequence for
standout, you'll need to create a new terminfo file with modified sgr, smso,
rmso, sitm and ritm entries:
$ mkdir $HOME/.terminfo/
$ screen_terminfo="screen"
$ infocmp "$screen_terminfo" | sed \
-e 's/^screen[^|]*|[^,]*,/screen-it|screen with italics support,/' \
-e 's/%?%p1%t;3%/%?%p1%t;7%/' \
-e 's/smso=[^,]*,/smso=\\E[7m,/' \
-e 's/rmso=[^,]*,/rmso=\\E[27m,/' \
-e '$s/$/ sitm=\\E[3m, ritm=\\E[23m,/' > /tmp/screen.terminfo
$ tic /tmp/screen.terminfo
And tell tmux to use it in ~/.tmux.conf:
set -g default-terminal "screen-it"
If your terminal supports 256 colors, use:
$ screen_terminfo="screen-256color"
instead of "screen". See the FAQ entry about 256 colors support for more info.
Also note that tmux will still display reverse video on terminals that do not
support italics.
If your urxvt cannot display italics at all, make sure you have an italics
capable font enabled, for example, add to ~/.Xdefaults:
urxvt.italicFont: xft:Bitstream Vera Sans Mono:italic:autohint=true
$Id$

View File

@@ -1,86 +0,0 @@
# $Id: GNUmakefile,v 1.122 2010-03-10 15:15:33 tcunha Exp $
#
# Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
#
# 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.
#
.PHONY: clean
VERSION= 1.2
#FDEBUG= 1
CC?= cc
CFLAGS+= -DBUILD="\"$(VERSION)\""
LDFLAGS+= -L/usr/local/lib
LIBS+=
# Sun CC
ifneq ($(shell ($(CC) -V 2>&1|awk '/Sun C/' || true)), )
CFLAGS+=-erroff=E_EMPTY_DECLARATION
FDEBUG=
endif
ifdef FDEBUG
CFLAGS+= -g -ggdb -DDEBUG
CFLAGS+= -Wno-long-long -Wall -W -Wnested-externs -Wformat=2
CFLAGS+= -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
CFLAGS+= -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
CFLAGS+= -Wundef -Wbad-function-cast -Winline -Wcast-align
endif
# This sort of sucks but gets rid of the stupid warning and should work on
# most platforms...
ifeq ($(shell (LC_ALL=C $(CC) -v 2>&1|awk '/gcc version 4|clang/') || true), )
CPPFLAGS:= -I. -I- $(CPPFLAGS)
else
CPPFLAGS:= -iquote. $(CPPFLAGS)
ifdef FDEBUG
CFLAGS+= -Wno-pointer-sign
endif
endif
PREFIX?= /usr/local
INSTALLDIR= install -d
INSTALLBIN= install -g bin -o root -m 555
INSTALLMAN= install -g bin -o root -m 444
SRCS= $(shell echo *.c|sed 's|osdep-[a-z0-9]*.c||g')
include config.mk
OBJS= $(patsubst %.c,%.o,$(SRCS))
all: tmux
tmux: $(OBJS)
$(CC) $(LDFLAGS) -o tmux $+ $(LIBS)
depend: $(SRCS)
$(CC) $(CPPFLAGS) $(CFLAGS) -MM $(SRCS) > .depend
clean:
rm -f tmux *.o *~ *.core *.log compat/*.o compat/*~
clean-depend:
rm -f .depend
clean-all: clean clean-depend
rm -f config.h config.mk
install: all
$(INSTALLDIR) $(DESTDIR)$(PREFIX)/bin
$(INSTALLBIN) tmux $(DESTDIR)$(PREFIX)/bin/tmux
$(INSTALLDIR) $(DESTDIR)$(PREFIX)/man/man1
$(INSTALLMAN) tmux.1 $(DESTDIR)$(PREFIX)/man/man1/tmux.1
-include .depend

View File

@@ -1,83 +0,0 @@
# $Id: Makefile,v 1.155 2010-03-10 15:15:33 tcunha Exp $
#
# Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
#
# 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.
#
.SUFFIXES: .c .o
.PHONY: clean
VERSION= 1.2
#FDEBUG= 1
CC?= cc
CFLAGS+= -DBUILD="\"$(VERSION)\""
LDFLAGS+= -L/usr/local/lib
LIBS+=
.ifdef FDEBUG
CFLAGS+= -g -ggdb -DDEBUG
CFLAGS+= -Wno-long-long -Wall -W -Wnested-externs -Wformat=2
CFLAGS+= -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
CFLAGS+= -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
CFLAGS+= -Wundef -Wbad-function-cast -Winline -Wcast-align
.endif
# This sort of sucks but gets rid of the stupid warning and should work on
# most platforms...
CCV!= (LC_ALL=C ${CC} -v 2>&1|awk '/gcc version 4|clang/') || true
.if empty(CCV)
CPPFLAGS:= -I. -I- -I/usr/local/include ${CPPFLAGS}
.else
CPPFLAGS:= -iquote. -I/usr/local/include ${CPPFLAGS}
.ifdef FDEBUG
CFLAGS+= -Wno-pointer-sign
.endif
.endif
PREFIX?= /usr/local
INSTALLDIR= install -d
INSTALLBIN= install -g bin -o root -m 555
INSTALLMAN= install -g bin -o root -m 444
SRCS!= echo *.c|sed 's|osdep-[a-z0-9]*.c||g'
.include "config.mk"
OBJS= ${SRCS:S/.c/.o/}
.c.o:
${CC} ${CPPFLAGS} ${CFLAGS} -c ${.IMPSRC} -o ${.TARGET}
all: tmux
tmux: ${OBJS}
${CC} ${LDFLAGS} -o tmux ${OBJS} ${LIBS}
depend:
mkdep ${CPPFLAGS} ${CFLAGS} ${SRCS:M*.c}
clean:
rm -f tmux *.o *~ *.core *.log compat/*.o compat/*~
clean-depend:
rm -f .depend
clean-all: clean clean-depend
rm -f config.h config.mk
install: all
${INSTALLDIR} ${DESTDIR}${PREFIX}/bin
${INSTALLBIN} tmux ${DESTDIR}${PREFIX}/bin/
${INSTALLDIR} ${DESTDIR}${PREFIX}/man/man1
${INSTALLMAN} tmux.1 ${DESTDIR}${PREFIX}/man/man1/

242
Makefile.am Normal file
View File

@@ -0,0 +1,242 @@
# $Id$
# Obvious program stuff.
bin_PROGRAMS = tmux
dist_man1_MANS = tmux.1
# Distribution tarball options.
EXTRA_DIST = \
CHANGES FAQ NOTES TODO examples compat \
array.h compat.h tmux.h osdep-*.c
dist-hook:
grep "^#found_debug=" configure
find $(distdir) -name .svn -type d|xargs rm -Rf
# Preprocessor flags.
CPPFLAGS += @XOPEN_DEFINES@
# glibc as usual does things ass-backwards and hides useful things by default,
# so everyone has to add this.
if IS_GLIBC
CFLAGS += -D_GNU_SOURCE
endif
# Set flags for gcc. gcc4 whines abouts silly stuff so it needs slightly
# different flags.
if IS_GCC
CFLAGS += -std=c99
if IS_DEBUG
CFLAGS += -g -ggdb -O0
CFLAGS += -Wno-long-long -Wall -W -Wnested-externs -Wformat=2
CFLAGS += -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
CFLAGS += -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
CFLAGS += -Wundef -Wbad-function-cast -Winline -Wcast-align
CPPFLAGS += -DDEBUG
endif
if IS_GCC4
CPPFLAGS += -iquote. -I/usr/local/include
if IS_DEBUG
CFLAGS += -Wno-pointer-sign
endif
else
CPPFLAGS += -I. -I- -I/usr/local/include
endif
endif
# Set flags for Solaris.
if IS_SUNOS
CPPFLAGS += -D_XPG4_2 -D__EXTENSIONS__ -D_POSIX_PTHREAD_SEMANTICS
endif
# Set flags for Sun CC.
if IS_SUNCC
CFLAGS += -erroff=E_EMPTY_DECLARATION
endif
# List of sources.
dist_tmux_SOURCES = \
arguments.c \
attributes.c \
cfg.c \
client.c \
clock.c \
cmd-attach-session.c \
cmd-bind-key.c \
cmd-break-pane.c \
cmd-capture-pane.c \
cmd-choose-buffer.c \
cmd-choose-client.c \
cmd-choose-session.c \
cmd-choose-window.c \
cmd-clear-history.c \
cmd-clock-mode.c \
cmd-command-prompt.c \
cmd-confirm-before.c \
cmd-copy-mode.c \
cmd-delete-buffer.c \
cmd-detach-client.c \
cmd-display-message.c \
cmd-display-panes.c \
cmd-find-window.c \
cmd-has-session.c \
cmd-if-shell.c \
cmd-join-pane.c \
cmd-kill-pane.c \
cmd-kill-server.c \
cmd-kill-session.c \
cmd-kill-window.c \
cmd-link-window.c \
cmd-list-buffers.c \
cmd-list-clients.c \
cmd-list-commands.c \
cmd-list-keys.c \
cmd-list-panes.c \
cmd-list-sessions.c \
cmd-list-windows.c \
cmd-list.c \
cmd-load-buffer.c \
cmd-lock-server.c \
cmd-move-window.c \
cmd-new-session.c \
cmd-new-window.c \
cmd-paste-buffer.c \
cmd-pipe-pane.c \
cmd-refresh-client.c \
cmd-rename-session.c \
cmd-rename-window.c \
cmd-resize-pane.c \
cmd-respawn-pane.c \
cmd-respawn-window.c \
cmd-rotate-window.c \
cmd-run-shell.c \
cmd-save-buffer.c \
cmd-select-layout.c \
cmd-select-pane.c \
cmd-select-window.c \
cmd-send-keys.c \
cmd-send-prefix.c \
cmd-server-info.c \
cmd-set-buffer.c \
cmd-set-environment.c \
cmd-set-option.c \
cmd-show-buffer.c \
cmd-show-environment.c \
cmd-show-messages.c \
cmd-show-options.c \
cmd-source-file.c \
cmd-split-window.c \
cmd-start-server.c \
cmd-string.c \
cmd-suspend-client.c \
cmd-swap-pane.c \
cmd-swap-window.c \
cmd-switch-client.c \
cmd-unbind-key.c \
cmd-unlink-window.c \
cmd.c \
colour.c \
environ.c \
format.c \
grid-utf8.c \
grid-view.c \
grid.c \
input-keys.c \
input.c \
job.c \
key-bindings.c \
key-string.c \
layout-custom.c \
layout-set.c \
layout.c \
log.c \
mode-key.c \
names.c \
options-table.c \
options.c \
paste.c \
resize.c \
screen-redraw.c \
screen-write.c \
screen.c \
server-client.c \
server-fn.c \
server-window.c \
server.c \
session.c \
signal.c \
status.c \
tmux.c \
tty-acs.c \
tty-keys.c \
tty-term.c \
tty.c \
utf8.c \
window-choose.c \
window-clock.c \
window-copy.c \
window.c \
xmalloc.c \
xterm-keys.c
nodist_tmux_SOURCES = osdep-@PLATFORM@.c
# Pile in all the compat/ stuff that is needed.
if NO_FORKPTY
nodist_tmux_SOURCES += compat/forkpty-@PLATFORM@.c
endif
if NO_IMSG
nodist_tmux_SOURCES += compat/imsg.c compat/imsg-buffer.c
endif
if NO_CLOSEFROM
nodist_tmux_SOURCES += compat/closefrom.c
endif
if NO_DAEMON
nodist_tmux_SOURCES += compat/daemon.c
endif
if NO_SETENV
nodist_tmux_SOURCES += compat/setenv.c
endif
if NO_STRLCAT
nodist_tmux_SOURCES += compat/strlcat.c
endif
if NO_STRLCPY
nodist_tmux_SOURCES += compat/strlcpy.c
endif
if NO_ASPRINTF
nodist_tmux_SOURCES += compat/asprintf.c
endif
if NO_FGETLN
nodist_tmux_SOURCES += compat/fgetln.c
endif
if NO_GETOPT
nodist_tmux_SOURCES += compat/getopt.c
endif
if NO_STRCASESTR
nodist_tmux_SOURCES += compat/strcasestr.c
endif
if NO_STRSEP
nodist_tmux_SOURCES += compat/strsep.c
endif
if NO_VIS
nodist_tmux_SOURCES += compat/vis.c compat/unvis.c
endif
if NO_STRTONUM
nodist_tmux_SOURCES += compat/strtonum.c
endif
if NO_B64_NTOP
nodist_tmux_SOURCES += compat/b64_ntop.c
endif
# Update SF web site.
upload-index.html: update-index.html
scp www/index.html www/main.css www/images/*.png \
${USER},tmux@web.sf.net:/home/groups/t/tm/tmux/htdocs
rm -f www/index.html www/images/small-*
update-index.html:
(cd www/images && \
rm -f small-* && \
for i in *.png; do \
convert "$$i" -resize 200x150 "small-$$i"; \
done \
)
sed "s/%%VERSION%%/${VERSION}/g" www/index.html.in >www/index.html

45
NOTES
View File

@@ -9,11 +9,27 @@ run on Solaris and AIX (although they haven't been tested in a while). It is
usable, although there remain a number of missing features and some remaining usable, although there remain a number of missing features and some remaining
bugs are expected. bugs are expected.
Since the 1.2 release that tmux depends on libevent. Download the stable If upgrading from 1.5, PLEASE NOTE:
version from: - The word-separators window option is now a session option.
- The options used to change the window attributes when an alert occurs were
removed. Each kind of alert has its own individual set of options.
- The ability to have a list of prefix keys was dropped in favour of two
separate options, prefix and prefix2.
Since the 1.2 release that tmux depends on libevent. Download it from:
http://www.monkey.org/~provos/libevent/ http://www.monkey.org/~provos/libevent/
To build tmux from a release tarball, do:
$ ./configure && make
$ sudo make install
To build from a version control checkout, the configure script must be
generated by running:
$ sh autogen.sh
tmux consists of a server part and multiple clients. The server is created when tmux consists of a server part and multiple clients. The server is created when
required and runs continuously unless killed by the user. Clients access the required and runs continuously unless killed by the user. Clients access the
server through a socket in /tmp. Multiple sessions may be created on a single server through a socket in /tmp. Multiple sessions may be created on a single
@@ -25,34 +41,11 @@ windows into several simultaneously displayed panes; and to bind and unbind
command keys (invoked preceded by a prefix key, by default ctrl-b). Please see command keys (invoked preceded by a prefix key, by default ctrl-b). Please see
the tmux(1) man page for further information. the tmux(1) man page for further information.
The following is a summary of major features implemented in this version:
- Basic multiplexing, window switching, attaching and detaching.
- Window listing and renaming.
- Key binding.
- Handling of client terminal resize.
- Terminal emulation sufficient to handle most curses applications.
- A optional status line (enabled by default).
- Window history and copy and paste.
- Support for VT100 line drawing characters.
- A large command set.
- Vertical window splitting and layout.
- Automatic server locking on inactivity by running an external command.
- A configuration file.
- UTF-8 support.
A more extensive, but rough, todo list is included in the TODO file. A more extensive, but rough, todo list is included in the TODO file.
tmux also depends on several features of the client terminal (TERM), if these tmux also depends on several features of the client terminal (TERM), if these
are missing it may refuse to run, or not behave correctly. are missing it may refuse to run, or not behave correctly.
tmux supports UTF-8. To use it, the utf8 option must be set on each window;
this may be turned on for all windows by setting it as a global option, see
tmux(1) and the FAQ file. As of 0.9, tmux attempts to autodetect a
UTF-8 capable terminal by checking the LC_ALL, LC_CTYPE and LANG environment
variables. list-clients may be used to check if this is detected correctly; if
not, the -u command-line flag may be specified.
A Vim syntax file is available in the examples directory. To install it: A Vim syntax file is available in the examples directory. To install it:
- Drop the file in the syntax directory in your runtimepath (such as - Drop the file in the syntax directory in your runtimepath (such as
@@ -86,4 +79,4 @@ start. Please contact me with any queries.
-- Nicholas Marriott <nicm@users.sf.net> -- Nicholas Marriott <nicm@users.sf.net>
$Id: NOTES,v 1.53 2010-03-10 15:18:11 tcunha Exp $ $Id$

141
TODO
View File

@@ -1,33 +1,17 @@
- window creation/idle time
- better errors when creating new windows/sessions (how?)
- implicitly add exec to the commands for new windows (switch to disable it)? - implicitly add exec to the commands for new windows (switch to disable it)?
- it would be nice to have multichar commands eg C-b K K - bring back detach-session to detach all clients on a session?
- commands:
extend list-clients to list clients attached to a session (-a for all?)
bring back detach-session to detach all clients on a session?
- allow fnmatch for -c, so that you can, eg, detach all clients - allow fnmatch for -c, so that you can, eg, detach all clients
- garbage collect window history (100 lines at a time?) if it hasn't been used - garbage collect window history (100 lines at a time?) if it hasn't been used
in $x time (need window creation/use times) in $x time
- lift SHRT_MAX limits for history?
- flags to centre screen in window - flags to centre screen in window
- better terminal emulation
- activity/bell should be per-window not per-link? what if it is cur win in - activity/bell should be per-window not per-link? what if it is cur win in
session not being watched? session not being watched?
- next prev word etc in command prompt
- many more info() displays for various things
- input.c is too complicated. simplify?
- use a better termcap internally instead of screen, perhaps xterm - use a better termcap internally instead of screen, perhaps xterm
- fix rxvt cursor fg issue (text under cursor can have non-white fg)
- should be able to move to a hidden pane and it would be moved into view. pane - should be able to move to a hidden pane and it would be moved into view. pane
number in status line/top-right would be cool for this number in status line/top-right would be cool for this
- support other mouse modes (highlight etc) and use it in copy mode - support other mouse modes (highlight etc) and use it in copy mode
- set-remain-on-exit is a bit of a hack, some way to do it generically? - set-remain-on-exit is a bit of a hack, some way to do it generically?
- set-option should be set-session-option and should be overall global options
also quiet, utf8 and maybe other flags?
-g is a bit unexpected in conf file
- clear window title on exit - clear window title on exit
- the output code (tty.c) could do with optimisation depending on term
capabilities
- would be nice to be able to use "--" to mark start of command w/ neww etc - would be nice to be able to use "--" to mark start of command w/ neww etc
to avoid quoting to avoid quoting
- make command sequences more usable: don't require space after ;, handle - make command sequences more usable: don't require space after ;, handle
@@ -38,11 +22,7 @@
"new-session" if-shell "[ -e $HOME/.tmux-session.conf ]" source-file "new-session" if-shell "[ -e $HOME/.tmux-session.conf ]" source-file
$HOME/.tmux-session.conf $HOME/.tmux-session.conf
- get it passing all the vttest tests that don't require resizing the terminal - get it passing all the vttest tests that don't require resizing the terminal
- esc seq to set window name and title should be documented, and name variant
should clear automatic-rename
- way to set socket path from config file - way to set socket path from config file
- XXX once env stuff is in, default-path and VISUAL/EDITOR should be picked up
when session is started
- what about utmp etc? can tmux update it like screen? setgid? - what about utmp etc? can tmux update it like screen? setgid?
- warts on current naming: - warts on current naming:
- display-time but message-fg/bg/attr - display-time but message-fg/bg/attr
@@ -50,48 +30,24 @@
- server-info - server-info
- up-pane/down-pane/swap-pane -U/swap-pane -D vs next-*/previous-* - up-pane/down-pane/swap-pane -U/swap-pane -D vs next-*/previous-*
- split-window -> split-pane?? - split-window -> split-pane??
- tidy up and prioritise todo list ;-)
- neww and attach can create a session if none exists?
would work fine with config file since
- a way for force-width/height to apply to only one pane (how?) - a way for force-width/height to apply to only one pane (how?)
- command to list what is actually running in each window with command line, - command to list what is actually running in each window with command line,
pid (need some adaption of the osdep code) pid (need some adaption of the osdep code)
- support for bce - support for bce
- it would be nice if the start/end line keys in copy mode were aware of
wrapped lines
- some way to force a screen to use the entire terminal even if it is forced - some way to force a screen to use the entire terminal even if it is forced
to be smaller by other clients. pan smaller terminal? (like screen F) to be smaller by other clients. pan smaller terminal? (like screen F)
-- idea of a "view" onto a window, need base x/y offsets -- idea of a "view" onto a window, need base x/y offsets for redraw
for redraw
- handle resize better in copy mode - handle resize better in copy mode
- way to copy stuff that is off screen due to resize - way to copy stuff that is off screen due to resize
- commands should be able to succeed or fail and have || or && for command - commands should be able to succeed or fail and have || or && for command
lists lists
- support the mouse wheel to scroll through history
- some way to KEEP a command running continually and just use its LAST line of - some way to KEEP a command running continually and just use its LAST line of
output output
- bind commands to mouse buttons
- UTF-8 to a non-UTF-8 terminal should not be able to balls up - UTF-8 to a non-UTF-8 terminal should not be able to balls up
the terminal - www/ruby-addressable; make regress the terminal - www/ruby-addressable; make regress
- copy mode needs a tidy/cleanup
- ability to save history (to buffer?)
- multiple keys could be done with tables, ie have prefixes go and instead
bind -n ^A prefix-table "default"
where prefix-table sets command lookup table and sets prefix flag, then next
key is looked up in that table
- UTF-8 should be a pointer into a combined string buffer
- check irssi (term_charset) works with UTF-8
- support esc-esc to quit in modes - support esc-esc to quit in modes
- fix ctrl+F1-F4 output. to what? - fix ctrl+F1-F4 output. to what?
- look into xterm clearing its selection when scrolling etc - better utf8 support: window names, prompt input, message display
- better utf8 support:
window names
prompt input
message display
copy and paste cursor and wide characters
...?
- option so that when session is destroyed, attach client to another session
rather than exiting
- session history for client and last-session command - session history for client and last-session command
- option to change status line colour when current window is in a mode? - option to change status line colour when current window is in a mode?
- option to move copy mode indicator into status line - option to move copy mode indicator into status line
@@ -99,37 +55,90 @@
- selection behaviour closer to vi in vi mode - selection behaviour closer to vi in vi mode
- live update: server started with -U connects to server, requests sessions and - live update: server started with -U connects to server, requests sessions and
windows, receives fds windows, receives fds
- convert status line history to be server global (anything else?)
- something for -t "last window in session" so a session can be used as a stack
- command to show a tree of sessions-windows-panes (active marked with *) - command to show a tree of sessions-windows-panes (active marked with *)
- sort out inheriting config from shell on new sessions/windows: - sort out inheriting config from shell on new sessions/windows:
should pick up default-path/termios/etc from client if possible, should pick up default-path/termios/etc from client if possible,
else leave empty/default else leave empty/default
- define custom layouts
- link panes into multiple windows - link panes into multiple windows
- -h option to capture-pane to capture the history as well
- bells should be passed between sessions with visual-bell etc - bells should be passed between sessions with visual-bell etc
- use screen-256color when started on 256 colour terminal?? - use screen-256color when started on 256 colour terminal??
- if-shell/run-shell should block further command execution in the same command - if-shell/run-shell should block further command execution in the same command
sequence until its shell exits, to allow them to be used from the config file sequence until its shell exits, to allow them to be used from the config file
- better session sharing: create-socket command to create socket somewhere (-r - better session sharing: create-socket command to create socket somewhere (-r
flag for readonly) flag for readonly)
- allow buffer to be specified when copying in copy mode - multiline status line (no?)
- multiline status line
- flag for absolute pane size to resize-pane - flag for absolute pane size to resize-pane
- sanity check input to socket - sanity check input to socket
- stdin fd should be passed up to parent so load-buffer and others could use it
for nonattaching clients
- environment should be set up for jobs
- select-buffer command
- fix jobs so they block in config file rather than executing at an arbitrary
future point -- need state stored in client so other clients can proceed
- rectangle copy:
when selecting leftward, cursor should be inside block per emacs
key to rotate corner at which cursor is
- double C-a should walk back over wrapped lines like C-e
- support title stack, both internally and externally - support title stack, both internally and externally
http://docs.freebsd.org/cgi/getmsg.cgi?fetch=1149299+0+archive/2010/freebsd-questions/20100207.freebsd-questions http://docs.freebsd.org/cgi/getmsg.cgi?fetch=1149299+0+archive/2010/freebsd-questions/20100207.freebsd-questions
- copy buffers should be global, limit can be server option, nuke copy-buffer
command
- command to show status line information briefly when it is off - command to show status line information briefly when it is off
- some way to pad # stuff with spaces, #!2T maybe
- a binding to "scroll down and exit at bottom" copy mode
- some way to pass keystrokes in copy mode through to underlying window
- last window update time and # replacement for it for display-message
- find-window across sessions - other ways to make session handling easier?
- ' and " should be parsed the same (eg "\e" vs '\e') in config and command
prompt?
- command to toggle selection not to move it in copy-mode
- why are alerts per-winlink? try per window?
- audit of escape sequence support vs xterm
- support binding keys to mouse (mouse-select-pane -> mouse-keys or something,
mouse click == select-pane -t %%, mouse scroll up == copy-mode)
- something for -t "last window in session" so a session can be used as a stack
- synchronous commands - client sends cmd and blocks, neww/splitw saves client
ptr then when program inside died, sends MSG_SOMETHING with wait status to
client
- documentation improvements - rlpowell's tutorial - build instructions
- bind commands to key sequences? -- make it so ALL keys go through a table,
first an implicit table in which C-b is the only default binding to a
command that says "next key from $othertable" and so on. means -n can
go away as well
- monitor, bell etc should monitor /all/ panes in the window not just one
- a history of commands that can be reversed (reverse member of each command,
and a buffer) info() when changing to same window
- way to add dest for break-pane; maybe some easier way to unbreak-pane
- case insensitive searching
- option to move status line to top
- configurable borders and empty space filler for when panes < window?
- mouse-select-pane will screw up with !MODE_MOUSE_STANDARD (it sets the
flag on w/o checking the others before calling tty_update_mode)
- multiple keys could be done with tables, ie have prefixes go and instead
bind -n ^A prefix-table "default"
where prefix-table sets command lookup table and sets prefix flag, then next
key is looked up in that table
- pass shell commands as argv rather than strings, allow them to be specified
in commands without quotes
- a command to choose from a generic list, so you can do eg
choose-list -l Abc,Moo,Blah "run-shell 'sh /my/choose/script %%'"
- numeric prefix in copy mode should be paste buffer for C-w
- named buffers and allow gaps in the stack
- get rid of separate UTF-8 cell stuff: add 1 byte to cell and store BMP as
uint16_t+3 bits of flags. anything <=0xffff is Unicode, higher are used to
build tree of combined characters/non-BMP (LRU dropped when full)
- entry in FAQ about what to do when someone does mkdir /tmp/tmux-1000
- show size under pane number in display-panes mode
- monitor-activity is broken in several ways with multiple clients
- monitor-activity should be more powerful (eg set a region)
- maybe a way to put pane names instead of window names in status line
- support for borderless panes
- run-shell/if-shell should support status_replace stuff
- wait-pane command or another way to make it synchronous/wait for command to
finish
- last-pane across sessions
- attach should take a pane and select it as well as attaching
- should default-path be a window option?
- option to put status line at top (why?)
- panes should have names like windows
- command-prompt doesn't work if made read-only. why?
- option to quote format eg #{session_name:quoted}
- formats need to be used for much much more stuff!
- formats need conditions for >0 (for #P)
- flags to find-window to select what is searched (title, name, content, history)
- fetch full command line on !Linux, and add option to strip prefixes
such as "sh " "/bin/sh " etc etc
- synchronize-windows option
- possibly support rxvt-unicode extended mouse input (1015)
- append to buffer in copy mode
* We need a tmux terminfo entry to document the extensions we are using in
upstream terminfo. Must NOT change (only add or remove) anything from
TERM=screen so we can fallback!

222
arguments.c Normal file
View File

@@ -0,0 +1,222 @@
/* $Id$ */
/*
* Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <stdlib.h>
#include <string.h>
#include "tmux.h"
/* Create an arguments set with no flags. */
struct args *
args_create(int argc, ...)
{
struct args *args;
va_list ap;
int i;
args = xcalloc(1, sizeof *args);
if ((args->flags = bit_alloc(SCHAR_MAX)) == NULL)
fatal("bit_alloc failed");
args->argc = argc;
if (argc == 0)
args->argv = NULL;
else
args->argv = xcalloc(argc, sizeof *args->argv);
va_start(ap, argc);
for (i = 0; i < argc; i++)
args->argv[i] = xstrdup(va_arg(ap, char *));
va_end(ap);
return (args);
}
/* Parse an argv and argc into a new argument set. */
struct args *
args_parse(const char *template, int argc, char **argv)
{
struct args *args;
char *ptr;
int opt;
args = xcalloc(1, sizeof *args);
if ((args->flags = bit_alloc(SCHAR_MAX)) == NULL)
fatal("bit_alloc failed");
optreset = 1;
optind = 1;
while ((opt = getopt(argc, argv, template)) != -1) {
if (opt < 0 || opt >= SCHAR_MAX)
continue;
if (opt == '?' || (ptr = strchr(template, opt)) == NULL) {
xfree(args->flags);
xfree(args);
return (NULL);
}
bit_set(args->flags, opt);
if (ptr[1] == ':') {
if (args->values[opt] != NULL)
xfree(args->values[opt]);
args->values[opt] = xstrdup(optarg);
}
}
argc -= optind;
argv += optind;
args->argc = argc;
args->argv = cmd_copy_argv(argc, argv);
return (args);
}
/* Free an arguments set. */
void
args_free(struct args *args)
{
u_int i;
cmd_free_argv(args->argc, args->argv);
for (i = 0; i < SCHAR_MAX; i++) {
if (args->values[i] != NULL)
xfree(args->values[i]);
}
xfree(args->flags);
xfree(args);
}
/* Print a set of arguments. */
size_t
args_print(struct args *args, char *buf, size_t len)
{
size_t off;
int i;
const char *quotes;
/* There must be at least one byte at the start. */
if (len == 0)
return (0);
off = 0;
/* Process the flags first. */
buf[off++] = '-';
for (i = 0; i < SCHAR_MAX; i++) {
if (!bit_test(args->flags, i) || args->values[i] != NULL)
continue;
if (off == len - 1) {
buf[off] = '\0';
return (len);
}
buf[off++] = i;
buf[off] = '\0';
}
if (off == 1)
buf[--off] = '\0';
/* Then the flags with arguments. */
for (i = 0; i < SCHAR_MAX; i++) {
if (!bit_test(args->flags, i) || args->values[i] == NULL)
continue;
if (off >= len) {
/* snprintf will have zero terminated. */
return (len);
}
if (strchr(args->values[i], ' ') != NULL)
quotes = "\"";
else
quotes = "";
off += xsnprintf(buf + off, len - off, "%s-%c %s%s%s",
off != 0 ? " " : "", i, quotes, args->values[i], quotes);
}
/* And finally the argument vector. */
for (i = 0; i < args->argc; i++) {
if (off >= len) {
/* snprintf will have zero terminated. */
return (len);
}
if (strchr(args->argv[i], ' ') != NULL)
quotes = "\"";
else
quotes = "";
off += xsnprintf(buf + off, len - off, "%s%s%s%s",
off != 0 ? " " : "", quotes, args->argv[i], quotes);
}
return (off);
}
/* Return if an argument is present. */
int
args_has(struct args *args, u_char ch)
{
return (bit_test(args->flags, ch));
}
/* Set argument value. */
void
args_set(struct args *args, u_char ch, const char *value)
{
if (args->values[ch] != NULL)
xfree(args->values[ch]);
if (value != NULL)
args->values[ch] = xstrdup(value);
else
args->values[ch] = NULL;
bit_set(args->flags, ch);
}
/* Get argument value. Will be NULL if it isn't present. */
const char *
args_get(struct args *args, u_char ch)
{
return (args->values[ch]);
}
/* Convert an argument value to a number. */
long long
args_strtonum(struct args *args,
u_char ch, long long minval, long long maxval, char **cause)
{
const char *errstr;
long long ll;
if (!args_has(args, ch)) {
*cause = xstrdup("missing");
return (0);
}
ll = strtonum(args->values[ch], minval, maxval, &errstr);
if (errstr != NULL) {
*cause = xstrdup(errstr);
return (0);
}
*cause = NULL;
return (ll);
}

View File

@@ -1,4 +1,4 @@
/* $Id: array.h,v 1.10 2010-02-08 18:29:32 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2006 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2006 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -47,7 +47,7 @@
} \ } \
} while (0) } while (0)
#define ARRAY_EMPTY(a) ((a) == NULL || (a)->num == 0) #define ARRAY_EMPTY(a) (((void *) (a)) == NULL || (a)->num == 0)
#define ARRAY_LENGTH(a) ((a)->num) #define ARRAY_LENGTH(a) ((a)->num)
#define ARRAY_DATA(a) ((a)->list) #define ARRAY_DATA(a) ((a)->list)

View File

@@ -1,4 +1,4 @@
/* $Id: attributes.c,v 1.3 2009-11-28 14:46:23 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Joshua Elsasser <josh@elsasser.org> * Copyright (c) 2009 Joshua Elsasser <josh@elsasser.org>
@@ -28,7 +28,7 @@ attributes_tostring(u_char attr)
static char buf[128]; static char buf[128];
if (attr == 0) if (attr == 0)
return ("default"); return ("none");
buf[0] = '\0'; buf[0] = '\0';
if (attr & GRID_ATTR_BRIGHT) if (attr & GRID_ATTR_BRIGHT)
@@ -63,7 +63,7 @@ attributes_fromstring(const char *str)
if (strchr(delimiters, str[strlen(str) - 1]) != NULL) if (strchr(delimiters, str[strlen(str) - 1]) != NULL)
return (-1); return (-1);
if (strcasecmp(str, "default") == 0) if (strcasecmp(str, "default") == 0 || strcasecmp(str, "none") == 0)
return (0); return (0);
attr = 0; attr = 0;

16
autogen.sh Normal file
View File

@@ -0,0 +1,16 @@
#!/bin/sh
# $Id$
[ -z "$AUTOMAKE_VERSION" ] && export AUTOMAKE_VERSION=1.10
[ -z "$AUTOCONF_VERSION" ] && export AUTOCONF_VERSION=2.65
die()
{
echo "$@" >&2
exit 1
}
mkdir -p etc
aclocal || die "aclocal failed"
automake --add-missing --force-missing --copy --foreign || die "automake failed"
autoreconf || die "autoreconf failed"

49
cfg.c
View File

@@ -1,4 +1,4 @@
/* $Id: cfg.c,v 1.26 2010-02-08 18:29:32 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -69,7 +69,7 @@ cfg_add_cause(struct causelist *causes, const char *fmt, ...)
/* /*
* Load configuration file. Returns -1 for an error with a list of messages in * Load configuration file. Returns -1 for an error with a list of messages in
* causes. Note that causes and ncauses must be initialised by the caller! * causes. Note that causes must be initialised by the caller!
*/ */
int int
load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes) load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes)
@@ -80,6 +80,7 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes)
size_t len; size_t len;
struct cmd_list *cmdlist; struct cmd_list *cmdlist;
struct cmd_ctx ctx; struct cmd_ctx ctx;
int retval;
if ((f = fopen(path, "rb")) == NULL) { if ((f = fopen(path, "rb")) == NULL) {
cfg_add_cause(causes, "%s: %s", path, strerror(errno)); cfg_add_cause(causes, "%s: %s", path, strerror(errno));
@@ -88,24 +89,40 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes)
n = 0; n = 0;
line = NULL; line = NULL;
retval = 0;
while ((buf = fgetln(f, &len))) { while ((buf = fgetln(f, &len))) {
if (buf[len - 1] == '\n') if (buf[len - 1] == '\n')
buf[len - 1] = '\0'; len--;
if (line != NULL)
line = xrealloc(line, 1, strlen(line) + len + 1);
else { else {
line = xrealloc(line, 1, len + 1); line = xmalloc(len + 1);
memcpy(line, buf, len); *line = '\0';
line[len] = '\0';
buf = line;
} }
/* Append buffer to line. strncat will terminate. */
strncat(line, buf, len);
n++; n++;
/* Continuation: get next line? */
len = strlen(line);
if (len > 0 && line[len - 1] == '\\') {
line[len - 1] = '\0';
continue;
}
buf = line;
line = NULL;
if (cmd_string_parse(buf, &cmdlist, &cause) != 0) { if (cmd_string_parse(buf, &cmdlist, &cause) != 0) {
xfree(buf);
if (cause == NULL) if (cause == NULL)
continue; continue;
cfg_add_cause(causes, "%s: %u: %s", path, n, cause); cfg_add_cause(causes, "%s: %u: %s", path, n, cause);
xfree(cause); xfree(cause);
continue; continue;
} } else
xfree(buf);
if (cmdlist == NULL) if (cmdlist == NULL)
continue; continue;
cfg_cause = NULL; cfg_cause = NULL;
@@ -125,19 +142,21 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes)
ctx.info = cfg_print; ctx.info = cfg_print;
cfg_cause = NULL; cfg_cause = NULL;
cmd_list_exec(cmdlist, &ctx); if (cmd_list_exec(cmdlist, &ctx) == 1)
retval = 1;
cmd_list_free(cmdlist); cmd_list_free(cmdlist);
if (cfg_cause != NULL) { if (cfg_cause != NULL) {
cfg_add_cause(causes, "%s: %d: %s", path, n, cfg_cause); cfg_add_cause(
causes, "%s: %d: %s", path, n, cfg_cause);
xfree(cfg_cause); xfree(cfg_cause);
continue;
} }
} }
if (line != NULL) if (line != NULL) {
cfg_add_cause(causes,
"%s: %d: line continuation at end of file", path, n);
xfree(line); xfree(line);
}
fclose(f); fclose(f);
if (ARRAY_LENGTH(causes) != 0) return (retval);
return (-1);
return (0);
} }

403
client.c
View File

@@ -1,4 +1,4 @@
/* $Id: client.c,v 1.90 2009-12-04 22:14:47 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -17,7 +17,6 @@
*/ */
#include <sys/types.h> #include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/un.h> #include <sys/un.h>
@@ -29,7 +28,6 @@
#include <pwd.h> #include <pwd.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <syslog.h>
#include <unistd.h> #include <unistd.h>
#include "tmux.h" #include "tmux.h"
@@ -38,93 +36,185 @@ struct imsgbuf client_ibuf;
struct event client_event; struct event client_event;
const char *client_exitmsg; const char *client_exitmsg;
int client_exitval; int client_exitval;
enum msgtype client_exittype;
int client_attached;
int client_connect(char *, int);
void client_send_identify(int); void client_send_identify(int);
void client_send_environ(void); void client_send_environ(void);
void client_write_server(enum msgtype, void *, size_t); void client_write_server(enum msgtype, void *, size_t);
void client_update_event(void); void client_update_event(void);
void client_signal(int, short, void *); void client_signal(int, short, void *);
void client_callback(int, short, void *); void client_callback(int, short, void *);
int client_dispatch(void); int client_dispatch_attached(void);
int client_dispatch_wait(void *);
struct imsgbuf * /* Connect client to server. */
client_init(char *path, int cmdflags, int flags) int
client_connect(char *path, int start_server)
{ {
struct sockaddr_un sa; struct sockaddr_un sa;
size_t size; size_t size;
int fd, mode; int fd;
#ifdef HAVE_SETPROCTITLE
char rpathbuf[MAXPATHLEN];
#endif
#ifdef HAVE_SETPROCTITLE
if (realpath(path, rpathbuf) == NULL)
strlcpy(rpathbuf, path, sizeof rpathbuf);
setproctitle("client (%s)", rpathbuf);
#endif
memset(&sa, 0, sizeof sa); memset(&sa, 0, sizeof sa);
sa.sun_family = AF_UNIX; sa.sun_family = AF_UNIX;
size = strlcpy(sa.sun_path, path, sizeof sa.sun_path); size = strlcpy(sa.sun_path, path, sizeof sa.sun_path);
if (size >= sizeof sa.sun_path) { if (size >= sizeof sa.sun_path) {
errno = ENAMETOOLONG; errno = ENAMETOOLONG;
goto not_found; return (-1);
} }
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
fatal("socket failed"); fatal("socket failed");
if (connect(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1) { if (connect(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1) {
if (!(cmdflags & CMD_STARTSERVER)) if (!start_server)
goto not_found; goto failed;
switch (errno) { switch (errno) {
case ECONNREFUSED: case ECONNREFUSED:
if (unlink(path) != 0) if (unlink(path) != 0)
goto not_found; goto failed;
/* FALLTHROUGH */ /* FALLTHROUGH */
case ENOENT: case ENOENT:
if ((fd = server_start(path)) == -1) if ((fd = server_start()) == -1)
goto start_failed; goto failed;
goto server_started; break;
default:
goto failed;
} }
goto not_found;
} }
server_started: setblocking(fd, 0);
if ((mode = fcntl(fd, F_GETFL)) == -1) return (fd);
fatal("fcntl failed");
if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1)
fatal("fcntl failed");
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
fatal("fcntl failed");
imsg_init(&client_ibuf, fd);
if (cmdflags & CMD_SENDENVIRON) failed:
client_send_environ(); close(fd);
if (isatty(STDIN_FILENO)) return (-1);
client_send_identify(flags);
return (&client_ibuf);
start_failed:
log_warnx("server failed to start");
return (NULL);
not_found:
log_warn("server not found");
return (NULL);
} }
/* Client main loop. */
int
client_main(int argc, char **argv, int flags)
{
struct cmd *cmd;
struct cmd_list *cmdlist;
struct msg_command_data cmddata;
int cmdflags, fd;
pid_t ppid;
enum msgtype msg;
char *cause;
/* Set up the initial command. */
cmdflags = 0;
if (shell_cmd != NULL) {
msg = MSG_SHELL;
cmdflags = CMD_STARTSERVER;
} else if (argc == 0) {
msg = MSG_COMMAND;
cmdflags = CMD_STARTSERVER|CMD_SENDENVIRON|CMD_CANTNEST;
} else {
msg = MSG_COMMAND;
/*
* It sucks parsing the command string twice (in client and
* later in server) but it is necessary to get the start server
* flag.
*/
if ((cmdlist = cmd_list_parse(argc, argv, &cause)) == NULL) {
log_warnx("%s", cause);
return (1);
}
cmdflags &= ~CMD_STARTSERVER;
TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
if (cmd->entry->flags & CMD_STARTSERVER)
cmdflags |= CMD_STARTSERVER;
if (cmd->entry->flags & CMD_SENDENVIRON)
cmdflags |= CMD_SENDENVIRON;
if (cmd->entry->flags & CMD_CANTNEST)
cmdflags |= CMD_CANTNEST;
}
cmd_list_free(cmdlist);
}
/*
* Check if this could be a nested session, if the command can't nest:
* if the socket path matches $TMUX, this is probably the same server.
*/
if (shell_cmd == NULL && environ_path != NULL &&
cmdflags & CMD_CANTNEST && strcmp(socket_path, environ_path) == 0) {
log_warnx("sessions should be nested with care. "
"unset $TMUX to force.");
return (1);
}
/* Initialise the client socket and start the server. */
fd = client_connect(socket_path, cmdflags & CMD_STARTSERVER);
if (fd == -1) {
log_warn("failed to connect to server");
return (1);
}
/* Set process title, log and signals now this is the client. */
#ifdef HAVE_SETPROCTITLE
setproctitle("client (%s)", socket_path);
#endif
logfile("client");
/* Create imsg. */
imsg_init(&client_ibuf, fd);
event_set(&client_event, fd, EV_READ, client_callback, shell_cmd);
/* Establish signal handlers. */
set_signals(client_signal);
/* Send initial environment. */
if (cmdflags & CMD_SENDENVIRON)
client_send_environ();
client_send_identify(flags);
/* Send first command. */
if (msg == MSG_COMMAND) {
/* Fill in command line arguments. */
cmddata.pid = environ_pid;
cmddata.idx = environ_idx;
/* Prepare command for server. */
cmddata.argc = argc;
if (cmd_pack_argv(
argc, argv, cmddata.argv, sizeof cmddata.argv) != 0) {
log_warnx("command too long");
return (1);
}
client_write_server(msg, &cmddata, sizeof cmddata);
} else if (msg == MSG_SHELL)
client_write_server(msg, NULL, 0);
/* Set the event and dispatch. */
client_update_event();
event_dispatch();
/* Print the exit message, if any, and exit. */
if (client_attached) {
if (client_exitmsg != NULL && !login_shell)
printf("[%s]\n", client_exitmsg);
ppid = getppid();
if (client_exittype == MSG_DETACHKILL && ppid > 1)
kill(ppid, SIGHUP);
}
return (client_exitval);
}
/* Send identify message to server with the file descriptors. */
void void
client_send_identify(int flags) client_send_identify(int flags)
{ {
struct msg_identify_data data; struct msg_identify_data data;
struct winsize ws;
char *term; char *term;
int fd; int fd;
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1)
fatal("ioctl(TIOCGWINSZ)");
data.flags = flags; data.flags = flags;
if (getcwd(data.cwd, sizeof data.cwd) == NULL) if (getcwd(data.cwd, sizeof data.cwd) == NULL)
@@ -139,8 +229,19 @@ client_send_identify(int flags)
fatal("dup failed"); fatal("dup failed");
imsg_compose(&client_ibuf, imsg_compose(&client_ibuf,
MSG_IDENTIFY, PROTOCOL_VERSION, -1, fd, &data, sizeof data); MSG_IDENTIFY, PROTOCOL_VERSION, -1, fd, &data, sizeof data);
if ((fd = dup(STDOUT_FILENO)) == -1)
fatal("dup failed");
imsg_compose(&client_ibuf,
MSG_STDOUT, PROTOCOL_VERSION, -1, fd, NULL, 0);
if ((fd = dup(STDERR_FILENO)) == -1)
fatal("dup failed");
imsg_compose(&client_ibuf,
MSG_STDERR, PROTOCOL_VERSION, -1, fd, NULL, 0);
} }
/* Forward entire environment to server. */
void void
client_send_environ(void) client_send_environ(void)
{ {
@@ -154,12 +255,14 @@ client_send_environ(void)
} }
} }
/* Write a message to the server without a file descriptor. */
void void
client_write_server(enum msgtype type, void *buf, size_t len) client_write_server(enum msgtype type, void *buf, size_t len)
{ {
imsg_compose(&client_ibuf, type, PROTOCOL_VERSION, -1, -1, buf, len); imsg_compose(&client_ibuf, type, PROTOCOL_VERSION, -1, -1, buf, len);
} }
/* Update client event based on whether it needs to read or read and write. */
void void
client_update_event(void) client_update_event(void)
{ {
@@ -169,102 +272,74 @@ client_update_event(void)
events = EV_READ; events = EV_READ;
if (client_ibuf.w.queued > 0) if (client_ibuf.w.queued > 0)
events |= EV_WRITE; events |= EV_WRITE;
event_set(&client_event, client_ibuf.fd, events, client_callback, NULL); event_set(
&client_event, client_ibuf.fd, events, client_callback, shell_cmd);
event_add(&client_event, NULL); event_add(&client_event, NULL);
} }
__dead void /* Callback to handle signals in the client. */
client_main(void)
{
struct event ev_sigcont, ev_sigterm, ev_sigwinch;
struct sigaction sigact;
logfile("client");
/* Note: event_init() has already been called. */
/* Set up signals. */
memset(&sigact, 0, sizeof sigact);
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = SA_RESTART;
sigact.sa_handler = SIG_IGN;
if (sigaction(SIGINT, &sigact, NULL) != 0)
fatal("sigaction failed");
if (sigaction(SIGPIPE, &sigact, NULL) != 0)
fatal("sigaction failed");
if (sigaction(SIGUSR1, &sigact, NULL) != 0)
fatal("sigaction failed");
if (sigaction(SIGUSR2, &sigact, NULL) != 0)
fatal("sigaction failed");
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
fatal("sigaction failed");
signal_set(&ev_sigcont, SIGCONT, client_signal, NULL);
signal_add(&ev_sigcont, NULL);
signal_set(&ev_sigterm, SIGTERM, client_signal, NULL);
signal_add(&ev_sigterm, NULL);
signal_set(&ev_sigwinch, SIGWINCH, client_signal, NULL);
signal_add(&ev_sigwinch, NULL);
/*
* imsg_read in the first client poll loop (before the terminal has
* been initialised) may have read messages into the buffer after the
* MSG_READY switched to here. Process anything outstanding now to
* avoid hanging waiting for messages that have already arrived.
*/
if (client_dispatch() != 0)
goto out;
/* Set the event and dispatch. */
client_update_event();
event_dispatch();
out:
/* Print the exit message, if any, and exit. */
if (client_exitmsg != NULL && !login_shell)
printf("[%s]\n", client_exitmsg);
exit(client_exitval);
}
/* ARGSUSED */ /* ARGSUSED */
void void
client_signal(int sig, unused short events, unused void *data) client_signal(int sig, unused short events, unused void *data)
{ {
struct sigaction sigact; struct sigaction sigact;
int status;
switch (sig) { if (!client_attached) {
case SIGTERM: switch (sig) {
client_exitmsg = "terminated"; case SIGCHLD:
client_exitval = 1; waitpid(WAIT_ANY, &status, WNOHANG);
client_write_server(MSG_EXITING, NULL, 0); break;
break; case SIGTERM:
case SIGWINCH: event_loopexit(NULL);
client_write_server(MSG_RESIZE, NULL, 0); break;
break; }
case SIGCONT: } else {
memset(&sigact, 0, sizeof sigact); switch (sig) {
sigemptyset(&sigact.sa_mask); case SIGHUP:
sigact.sa_flags = SA_RESTART; client_exitmsg = "lost tty";
sigact.sa_handler = SIG_IGN; client_exitval = 1;
if (sigaction(SIGTSTP, &sigact, NULL) != 0) client_write_server(MSG_EXITING, NULL, 0);
fatal("sigaction failed"); break;
client_write_server(MSG_WAKEUP, NULL, 0); case SIGTERM:
break; client_exitmsg = "terminated";
client_exitval = 1;
client_write_server(MSG_EXITING, NULL, 0);
break;
case SIGWINCH:
client_write_server(MSG_RESIZE, NULL, 0);
break;
case SIGCONT:
memset(&sigact, 0, sizeof sigact);
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = SA_RESTART;
sigact.sa_handler = SIG_IGN;
if (sigaction(SIGTSTP, &sigact, NULL) != 0)
fatal("sigaction failed");
client_write_server(MSG_WAKEUP, NULL, 0);
break;
}
} }
client_update_event(); client_update_event();
} }
/* Callback for client imsg read events. */
/* ARGSUSED */ /* ARGSUSED */
void void
client_callback(unused int fd, short events, unused void *data) client_callback(unused int fd, short events, void *data)
{ {
ssize_t n; ssize_t n;
int retval;
if (events & EV_READ) { if (events & EV_READ) {
if ((n = imsg_read(&client_ibuf)) == -1 || n == 0) if ((n = imsg_read(&client_ibuf)) == -1 || n == 0)
goto lost_server; goto lost_server;
if (client_dispatch() != 0) { if (client_attached)
retval = client_dispatch_attached();
else
retval = client_dispatch_wait(data);
if (retval != 0) {
event_loopexit(NULL); event_loopexit(NULL);
return; return;
} }
@@ -284,8 +359,76 @@ lost_server:
event_loopexit(NULL); event_loopexit(NULL);
} }
/* Dispatch imsgs when in wait state (before MSG_READY). */
int int
client_dispatch(void) client_dispatch_wait(void *data)
{
struct imsg imsg;
ssize_t n, datalen;
struct msg_shell_data shelldata;
struct msg_exit_data exitdata;
const char *shellcmd = data;
if ((n = imsg_read(&client_ibuf)) == -1 || n == 0)
fatalx("imsg_read failed");
for (;;) {
if ((n = imsg_get(&client_ibuf, &imsg)) == -1)
fatalx("imsg_get failed");
if (n == 0)
return (0);
datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
switch (imsg.hdr.type) {
case MSG_EXIT:
case MSG_SHUTDOWN:
if (datalen != sizeof exitdata) {
if (datalen != 0)
fatalx("bad MSG_EXIT size");
} else {
memcpy(&exitdata, imsg.data, sizeof exitdata);
client_exitval = exitdata.retcode;
}
imsg_free(&imsg);
return (-1);
case MSG_READY:
if (datalen != 0)
fatalx("bad MSG_READY size");
client_attached = 1;
break;
case MSG_VERSION:
if (datalen != 0)
fatalx("bad MSG_VERSION size");
log_warnx("protocol version mismatch (client %u, "
"server %u)", PROTOCOL_VERSION, imsg.hdr.peerid);
client_exitval = 1;
imsg_free(&imsg);
return (-1);
case MSG_SHELL:
if (datalen != sizeof shelldata)
fatalx("bad MSG_SHELL size");
memcpy(&shelldata, imsg.data, sizeof shelldata);
shelldata.shell[(sizeof shelldata.shell) - 1] = '\0';
clear_signals(0);
shell_exec(shelldata.shell, shellcmd);
/* NOTREACHED */
default:
fatalx("unexpected message");
}
imsg_free(&imsg);
}
}
/* Dispatch imsgs in attached state (after MSG_READY). */
/* ARGSUSED */
int
client_dispatch_attached(void)
{ {
struct imsg imsg; struct imsg imsg;
struct msg_lock_data lockdata; struct msg_lock_data lockdata;
@@ -301,15 +444,21 @@ client_dispatch(void)
log_debug("client got %d", imsg.hdr.type); log_debug("client got %d", imsg.hdr.type);
switch (imsg.hdr.type) { switch (imsg.hdr.type) {
case MSG_DETACHKILL:
case MSG_DETACH: case MSG_DETACH:
if (datalen != 0) if (datalen != 0)
fatalx("bad MSG_DETACH size"); fatalx("bad MSG_DETACH size");
client_exittype = imsg.hdr.type;
if (imsg.hdr.type == MSG_DETACHKILL)
client_exitmsg = "detached and SIGHUP";
else
client_exitmsg = "detached";
client_write_server(MSG_EXITING, NULL, 0); client_write_server(MSG_EXITING, NULL, 0);
client_exitmsg = "detached";
break; break;
case MSG_EXIT: case MSG_EXIT:
if (datalen != 0) if (datalen != 0 &&
datalen != sizeof (struct msg_exit_data))
fatalx("bad MSG_EXIT size"); fatalx("bad MSG_EXIT size");
client_write_server(MSG_EXITING, NULL, 0); client_write_server(MSG_EXITING, NULL, 0);

View File

@@ -1,4 +1,4 @@
/* $Id: clock.c,v 1.9 2009-12-04 22:14:47 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-attach-session.c,v 1.36 2010-02-08 18:27:34 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,37 +28,37 @@ int cmd_attach_session_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_attach_session_entry = { const struct cmd_entry cmd_attach_session_entry = {
"attach-session", "attach", "attach-session", "attach",
"drt:", 0, 0,
"[-dr] " CMD_TARGET_SESSION_USAGE, "[-dr] " CMD_TARGET_SESSION_USAGE,
CMD_CANTNEST|CMD_STARTSERVER|CMD_SENDENVIRON, "dr", CMD_CANTNEST|CMD_STARTSERVER|CMD_SENDENVIRON,
cmd_target_init, NULL,
cmd_target_parse, NULL,
cmd_attach_session_exec, cmd_attach_session_exec
cmd_target_free,
cmd_target_print
}; };
int int
cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct session *s; struct session *s;
struct client *c; struct client *c;
const char *update; const char *update;
char *overrides, *cause; char *overrides, *cause;
u_int i; u_int i;
if (ARRAY_LENGTH(&sessions) == 0) { if (RB_EMPTY(&sessions)) {
ctx->error(ctx, "no sessions"); ctx->error(ctx, "no sessions");
return (-1); return (-1);
} }
if ((s = cmd_find_session(ctx, data->target)) == NULL)
if ((s = cmd_find_session(ctx, args_get(args, 't'), 1)) == NULL)
return (-1); return (-1);
if (ctx->cmdclient == NULL && ctx->curclient == NULL) if (ctx->cmdclient == NULL && ctx->curclient == NULL)
return (0); return (0);
if (ctx->cmdclient == NULL) { if (ctx->cmdclient == NULL) {
if (cmd_check_flag(data->chflags, 'd')) { if (args_has(self->args, 'd')) {
/* /*
* Can't use server_write_session in case attaching to * Can't use server_write_session in case attaching to
* the same session as currently attached to. * the same session as currently attached to.
@@ -74,7 +74,9 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx)
} }
ctx->curclient->session = s; ctx->curclient->session = s;
session_update_activity(s);
server_redraw_client(ctx->curclient); server_redraw_client(ctx->curclient);
s->curw->flags &= ~WINLINK_ALERTFLAGS;
} else { } else {
if (!(ctx->cmdclient->flags & CLIENT_TERMINAL)) { if (!(ctx->cmdclient->flags & CLIENT_TERMINAL)) {
ctx->error(ctx, "not a terminal"); ctx->error(ctx, "not a terminal");
@@ -89,19 +91,21 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx)
return (-1); return (-1);
} }
if (cmd_check_flag(data->chflags, 'r')) if (args_has(self->args, 'r'))
ctx->cmdclient->flags |= CLIENT_READONLY; ctx->cmdclient->flags |= CLIENT_READONLY;
if (cmd_check_flag(data->chflags, 'd')) if (args_has(self->args, 'd'))
server_write_session(s, MSG_DETACH, NULL, 0); server_write_session(s, MSG_DETACH, NULL, 0);
ctx->cmdclient->session = s; ctx->cmdclient->session = s;
session_update_activity(s);
server_write_client(ctx->cmdclient, MSG_READY, NULL, 0); server_write_client(ctx->cmdclient, MSG_READY, NULL, 0);
update = options_get_string(&s->options, "update-environment"); update = options_get_string(&s->options, "update-environment");
environ_update(update, &ctx->cmdclient->environ, &s->environ); environ_update(update, &ctx->cmdclient->environ, &s->environ);
server_redraw_client(ctx->cmdclient); server_redraw_client(ctx->cmdclient);
s->curw->flags &= ~WINLINK_ALERTFLAGS;
} }
recalculate_sizes(); recalculate_sizes();
server_update_socket(); server_update_socket();

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-bind-key.c,v 1.28 2010-01-25 17:12:44 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -26,137 +26,88 @@
* Bind a key to a command, this recurses through cmd_*. * Bind a key to a command, this recurses through cmd_*.
*/ */
int cmd_bind_key_parse(struct cmd *, int, char **, char **); int cmd_bind_key_check(struct args *);
int cmd_bind_key_exec(struct cmd *, struct cmd_ctx *); int cmd_bind_key_exec(struct cmd *, struct cmd_ctx *);
void cmd_bind_key_free(struct cmd *);
size_t cmd_bind_key_print(struct cmd *, char *, size_t);
int cmd_bind_key_table(struct cmd *, struct cmd_ctx *); int cmd_bind_key_table(struct cmd *, struct cmd_ctx *, int);
struct cmd_bind_key_data {
int key;
int can_repeat;
struct cmd_list *cmdlist;
int command_key;
char *tablename;
char *modecmd;
};
const struct cmd_entry cmd_bind_key_entry = { const struct cmd_entry cmd_bind_key_entry = {
"bind-key", "bind", "bind-key", "bind",
"cnrt:", 1, -1,
"[-cnr] [-t key-table] key command [arguments]", "[-cnr] [-t key-table] key command [arguments]",
0, "", 0,
NULL, NULL,
cmd_bind_key_parse, cmd_bind_key_check,
cmd_bind_key_exec, cmd_bind_key_exec
cmd_bind_key_free,
cmd_bind_key_print
}; };
int int
cmd_bind_key_parse(struct cmd *self, int argc, char **argv, char **cause) cmd_bind_key_check(struct args *args)
{ {
struct cmd_bind_key_data *data; if (args_has(args, 't')) {
int opt, no_prefix = 0; if (args->argc != 2)
return (-1);
self->data = data = xmalloc(sizeof *data);
data->can_repeat = 0;
data->cmdlist = NULL;
data->command_key = 0;
data->tablename = NULL;
data->modecmd = NULL;
while ((opt = getopt(argc, argv, "cnrt:")) != -1) {
switch (opt) {
case 'c':
data->command_key = 1;
break;
case 'n':
no_prefix = 1;
break;
case 'r':
data->can_repeat = 1;
break;
case 't':
if (data->tablename == NULL)
data->tablename = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc < 1)
goto usage;
if ((data->key = key_string_lookup_string(argv[0])) == KEYC_NONE) {
xasprintf(cause, "unknown key: %s", argv[0]);
goto error;
}
if (!no_prefix)
data->key |= KEYC_PREFIX;
argc--;
argv++;
if (data->tablename != NULL) {
if (argc != 1)
goto usage;
data->modecmd = xstrdup(argv[0]);
} else { } else {
if ((data->cmdlist = cmd_list_parse(argc, argv, cause)) == NULL) if (args->argc < 2)
goto error; return (-1);
}
return (0);
}
int
cmd_bind_key_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
char *cause;
struct cmd_list *cmdlist;
int key;
key = key_string_lookup_string(args->argv[0]);
if (key == KEYC_NONE) {
ctx->error(ctx, "unknown key: %s", args->argv[0]);
return (-1);
} }
return (0); if (args_has(args, 't'))
return (cmd_bind_key_table(self, ctx, key));
usage: cmdlist = cmd_list_parse(args->argc - 1, args->argv + 1, &cause);
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage); if (cmdlist == NULL) {
ctx->error(ctx, "%s", cause);
error: xfree(cause);
self->entry->free(self); return (-1);
return (-1); }
}
int
cmd_bind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
{
struct cmd_bind_key_data *data = self->data;
if (data == NULL)
return (0);
if (data->tablename != NULL)
return (cmd_bind_key_table(self, ctx));
key_bindings_add(data->key, data->can_repeat, data->cmdlist);
data->cmdlist = NULL; /* avoid free */
if (!args_has(args, 'n'))
key |= KEYC_PREFIX;
key_bindings_add(key, args_has(args, 'r'), cmdlist);
return (0); return (0);
} }
int int
cmd_bind_key_table(struct cmd *self, struct cmd_ctx *ctx) cmd_bind_key_table(struct cmd *self, struct cmd_ctx *ctx, int key)
{ {
struct cmd_bind_key_data *data = self->data; struct args *args = self->args;
const char *tablename;
const struct mode_key_table *mtab; const struct mode_key_table *mtab;
struct mode_key_binding *mbind, mtmp; struct mode_key_binding *mbind, mtmp;
enum mode_key_cmd cmd; enum mode_key_cmd cmd;
if ((mtab = mode_key_findtable(data->tablename)) == NULL) { tablename = args_get(args, 't');
ctx->error(ctx, "unknown key table: %s", data->tablename); if ((mtab = mode_key_findtable(tablename)) == NULL) {
ctx->error(ctx, "unknown key table: %s", tablename);
return (-1); return (-1);
} }
cmd = mode_key_fromstring(mtab->cmdstr, data->modecmd); cmd = mode_key_fromstring(mtab->cmdstr, args->argv[1]);
if (cmd == MODEKEY_NONE) { if (cmd == MODEKEY_NONE) {
ctx->error(ctx, "unknown command: %s", data->modecmd); ctx->error(ctx, "unknown command: %s", args->argv[1]);
return (-1); return (-1);
} }
mtmp.key = data->key & ~KEYC_PREFIX; mtmp.key = key;
mtmp.mode = data->command_key ? 1 : 0; mtmp.mode = !!args_has(args, 'c');
if ((mbind = SPLAY_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) { if ((mbind = RB_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) {
mbind->cmd = cmd; mbind->cmd = cmd;
return (0); return (0);
} }
@@ -164,39 +115,6 @@ cmd_bind_key_table(struct cmd *self, struct cmd_ctx *ctx)
mbind->key = mtmp.key; mbind->key = mtmp.key;
mbind->mode = mtmp.mode; mbind->mode = mtmp.mode;
mbind->cmd = cmd; mbind->cmd = cmd;
SPLAY_INSERT(mode_key_tree, mtab->tree, mbind); RB_INSERT(mode_key_tree, mtab->tree, mbind);
return (0); return (0);
} }
void
cmd_bind_key_free(struct cmd *self)
{
struct cmd_bind_key_data *data = self->data;
if (data->cmdlist != NULL)
cmd_list_free(data->cmdlist);
if (data->tablename != NULL)
xfree(data->tablename);
if (data->modecmd != NULL)
xfree(data->modecmd);
xfree(data);
}
size_t
cmd_bind_key_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_bind_key_data *data = self->data;
size_t off = 0;
const char *skey;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len) {
skey = key_string_lookup_key(data->key);
off += xsnprintf(buf + off, len - off, " %s ", skey);
}
if (off < len)
off += cmd_list_print(data->cmdlist, buf + off, len - off);
return (off);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-break-pane.c,v 1.11 2009-12-04 22:14:47 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,19 +30,18 @@ int cmd_break_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_break_pane_entry = { const struct cmd_entry cmd_break_pane_entry = {
"break-pane", "breakp", "break-pane", "breakp",
CMD_TARGET_PANE_USAGE " [-d]", "dt:", 0, 0,
0, "d", "[-d] " CMD_TARGET_PANE_USAGE,
cmd_target_init, 0,
cmd_target_parse, NULL,
cmd_break_pane_exec, NULL,
cmd_target_free, cmd_break_pane_exec
cmd_target_print
}; };
int int
cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct winlink *wl; struct winlink *wl;
struct session *s; struct session *s;
struct window_pane *wp; struct window_pane *wp;
@@ -50,7 +49,7 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
char *cause; char *cause;
int base_idx; int base_idx;
if ((wl = cmd_find_pane(ctx, data->target, &s, &wp)) == NULL) if ((wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp)) == NULL)
return (-1); return (-1);
if (window_count_panes(wl->window) == 1) { if (window_count_panes(wl->window) == 1) {
@@ -58,12 +57,18 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
return (-1); return (-1);
} }
TAILQ_REMOVE(&wl->window->panes, wp, entry); w = wl->window;
if (wl->window->active == wp) { TAILQ_REMOVE(&w->panes, wp, entry);
wl->window->active = TAILQ_PREV(wp, window_panes, entry); if (wp == w->active) {
if (wl->window->active == NULL) w->active = w->last;
wl->window->active = TAILQ_NEXT(wp, entry); w->last = NULL;
} if (w->active == NULL) {
w->active = TAILQ_PREV(wp, window_panes, entry);
if (w->active == NULL)
w->active = TAILQ_NEXT(wp, entry);
}
} else if (wp == w->last)
w->last = NULL;
layout_close_pane(wp); layout_close_pane(wp);
w = wp->window = window_create1(s->sx, s->sy); w = wp->window = window_create1(s->sx, s->sy);
@@ -74,7 +79,7 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
base_idx = options_get_number(&s->options, "base-index"); base_idx = options_get_number(&s->options, "base-index");
wl = session_attach(s, w, -1 - base_idx, &cause); /* can't fail */ wl = session_attach(s, w, -1 - base_idx, &cause); /* can't fail */
if (!cmd_check_flag(data->chflags, 'd')) if (!args_has(self->args, 'd'))
session_select(s, wl->idx); session_select(s, wl->idx);
server_redraw_session(s); server_redraw_session(s);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-capture-pane.c,v 1.3 2010-01-22 17:29:19 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Jonathan Alvarado <radobobo@users.sourceforge.net> * Copyright (c) 2009 Jonathan Alvarado <radobobo@users.sourceforge.net>
@@ -18,6 +18,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include "tmux.h" #include "tmux.h"
@@ -30,35 +31,64 @@ int cmd_capture_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_capture_pane_entry = { const struct cmd_entry cmd_capture_pane_entry = {
"capture-pane", "capturep", "capture-pane", "capturep",
CMD_BUFFER_PANE_USAGE, "b:E:S:t:", 0, 0,
0, "", "[-b buffer-index] [-E end-line] [-S start-line] [-t target-pane]",
cmd_buffer_init, 0,
cmd_buffer_parse, NULL,
cmd_capture_pane_exec, NULL,
cmd_buffer_free, cmd_capture_pane_exec
cmd_buffer_print
}; };
int int
cmd_capture_pane_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_capture_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_buffer_data *data = self->data; struct args *args = self->args;
struct window_pane *wp; struct window_pane *wp;
char *buf, *line; char *buf, *line, *cause;
struct screen *s; struct screen *s;
struct session *sess; struct grid *gd;
u_int i, limit; int buffer, n;
u_int i, limit, top, bottom, tmp;
size_t len, linelen; size_t len, linelen;
if (cmd_find_pane(ctx, data->target, &sess, &wp) == NULL) if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL)
return (-1); return (-1);
s = &wp->base; s = &wp->base;
gd = s->grid;
buf = NULL; buf = NULL;
len = 0; len = 0;
for (i = 0; i < screen_size_y(s); i++) { n = args_strtonum(args, 'S', INT_MIN, SHRT_MAX, &cause);
line = grid_view_string_cells(s->grid, 0, i, screen_size_x(s)); if (cause != NULL) {
top = gd->hsize;
xfree(cause);
} else if (n < 0 && (u_int) -n > gd->hsize)
top = 0;
else
top = gd->hsize + n;
if (top > gd->hsize + gd->sy - 1)
top = gd->hsize + gd->sy - 1;
n = args_strtonum(args, 'E', INT_MIN, SHRT_MAX, &cause);
if (cause != NULL) {
bottom = gd->hsize + gd->sy - 1;
xfree(cause);
} else if (n < 0 && (u_int) -n > gd->hsize)
bottom = 0;
else
bottom = gd->hsize + n;
if (bottom > gd->hsize + gd->sy - 1)
bottom = gd->hsize + gd->sy - 1;
if (bottom < top) {
tmp = bottom;
bottom = top;
top = tmp;
}
for (i = top; i <= bottom; i++) {
line = grid_string_cells(s->grid, 0, i, screen_size_x(s));
linelen = strlen(line); linelen = strlen(line);
buf = xrealloc(buf, 1, len + linelen + 1); buf = xrealloc(buf, 1, len + linelen + 1);
@@ -69,15 +99,26 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
xfree(line); xfree(line);
} }
limit = options_get_number(&sess->options, "buffer-limit"); limit = options_get_number(&global_options, "buffer-limit");
if (data->buffer == -1) {
paste_add(&sess->buffers, buf, len, limit); if (!args_has(args, 'b')) {
paste_add(&global_buffers, buf, len, limit);
return (0); return (0);
} }
if (paste_replace(&sess->buffers, data->buffer, buf, len) != 0) {
ctx->error(ctx, "no buffer %d", data->buffer); buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
if (cause != NULL) {
ctx->error(ctx, "buffer %s", cause);
xfree(buf);
xfree(cause);
return (-1);
}
if (paste_replace(&global_buffers, buffer, buf, len) != 0) {
ctx->error(ctx, "no buffer %d", buffer);
xfree(buf); xfree(buf);
return (-1); return (-1);
} }
return (0); return (0);
} }

143
cmd-choose-buffer.c Normal file
View File

@@ -0,0 +1,143 @@
/* $Id$ */
/*
* Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <ctype.h>
#include "tmux.h"
/*
* Enter choice mode to choose a buffer.
*/
int cmd_choose_buffer_exec(struct cmd *, struct cmd_ctx *);
void cmd_choose_buffer_callback(void *, int);
void cmd_choose_buffer_free(void *);
const struct cmd_entry cmd_choose_buffer_entry = {
"choose-buffer", NULL,
"t:", 0, 1,
CMD_TARGET_WINDOW_USAGE " [template]",
0,
NULL,
NULL,
cmd_choose_buffer_exec
};
struct cmd_choose_buffer_data {
struct client *client;
char *template;
};
int
cmd_choose_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct cmd_choose_buffer_data *cdata;
struct winlink *wl;
struct paste_buffer *pb;
u_int idx;
char *tmp;
if (ctx->curclient == NULL) {
ctx->error(ctx, "must be run interactively");
return (-1);
}
if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
return (-1);
if (paste_get_top(&global_buffers) == NULL)
return (0);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
return (0);
idx = 0;
while ((pb = paste_walk_stack(&global_buffers, &idx)) != NULL) {
tmp = paste_print(pb, 50);
window_choose_add(wl->window->active, idx - 1,
"%u: %zu bytes: \"%s\"", idx - 1, pb->size, tmp);
xfree(tmp);
}
cdata = xmalloc(sizeof *cdata);
if (args->argc != 0)
cdata->template = xstrdup(args->argv[0]);
else
cdata->template = xstrdup("paste-buffer -b '%%'");
cdata->client = ctx->curclient;
cdata->client->references++;
window_choose_ready(wl->window->active,
0, cmd_choose_buffer_callback, cmd_choose_buffer_free, cdata);
return (0);
}
void
cmd_choose_buffer_callback(void *data, int idx)
{
struct cmd_choose_buffer_data *cdata = data;
struct cmd_list *cmdlist;
struct cmd_ctx ctx;
char *template, *cause, tmp[16];
if (idx == -1)
return;
if (cdata->client->flags & CLIENT_DEAD)
return;
xsnprintf(tmp, sizeof tmp, "%u", idx);
template = cmd_template_replace(cdata->template, tmp, 1);
if (cmd_string_parse(template, &cmdlist, &cause) != 0) {
if (cause != NULL) {
*cause = toupper((u_char) *cause);
status_message_set(cdata->client, "%s", cause);
xfree(cause);
}
xfree(template);
return;
}
xfree(template);
ctx.msgdata = NULL;
ctx.curclient = cdata->client;
ctx.error = key_bindings_error;
ctx.print = key_bindings_print;
ctx.info = key_bindings_info;
ctx.cmdclient = NULL;
cmd_list_exec(cmdlist, &ctx);
cmd_list_free(cmdlist);
}
void
cmd_choose_buffer_free(void *data)
{
struct cmd_choose_buffer_data *cdata = data;
cdata->client->references--;
xfree(cdata->template);
xfree(cdata);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-choose-client.c,v 1.4 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -33,13 +33,12 @@ void cmd_choose_client_free(void *);
const struct cmd_entry cmd_choose_client_entry = { const struct cmd_entry cmd_choose_client_entry = {
"choose-client", NULL, "choose-client", NULL,
"t:", 0, 1,
CMD_TARGET_WINDOW_USAGE " [template]", CMD_TARGET_WINDOW_USAGE " [template]",
CMD_ARG01, "", 0,
cmd_target_init, NULL,
cmd_target_parse, NULL,
cmd_choose_client_exec, cmd_choose_client_exec
cmd_target_free,
cmd_target_print
}; };
struct cmd_choose_client_data { struct cmd_choose_client_data {
@@ -50,7 +49,7 @@ struct cmd_choose_client_data {
int int
cmd_choose_client_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_choose_client_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct cmd_choose_client_data *cdata; struct cmd_choose_client_data *cdata;
struct winlink *wl; struct winlink *wl;
struct client *c; struct client *c;
@@ -61,7 +60,7 @@ cmd_choose_client_exec(struct cmd *self, struct cmd_ctx *ctx)
return (-1); return (-1);
} }
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
return (-1); return (-1);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0) if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
@@ -77,14 +76,16 @@ cmd_choose_client_exec(struct cmd *self, struct cmd_ctx *ctx)
idx++; idx++;
window_choose_add(wl->window->active, i, window_choose_add(wl->window->active, i,
"%s: %s [%ux%u %s]%s", c->tty.path, "%s: %s [%ux%u %s]%s%s", c->tty.path,
c->session->name, c->tty.sx, c->tty.sy, c->session->name, c->tty.sx, c->tty.sy,
c->tty.termname, c->tty.flags & TTY_UTF8 ? " (utf8)" : ""); c->tty.termname,
c->tty.flags & TTY_UTF8 ? " (utf8)" : "",
c->flags & CLIENT_READONLY ? " (ro)" : "");
} }
cdata = xmalloc(sizeof *cdata); cdata = xmalloc(sizeof *cdata);
if (data->arg != NULL) if (args->argc != 0)
cdata->template = xstrdup(data->arg); cdata->template = xstrdup(args->argv[0]);
else else
cdata->template = xstrdup("detach-client -t '%%'"); cdata->template = xstrdup("detach-client -t '%%'");
cdata->client = ctx->curclient; cdata->client = ctx->curclient;

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-choose-session.c,v 1.15 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -33,13 +33,12 @@ void cmd_choose_session_free(void *);
const struct cmd_entry cmd_choose_session_entry = { const struct cmd_entry cmd_choose_session_entry = {
"choose-session", NULL, "choose-session", NULL,
"t:", 0, 1,
CMD_TARGET_WINDOW_USAGE " [template]", CMD_TARGET_WINDOW_USAGE " [template]",
CMD_ARG01, "", 0,
cmd_target_init, NULL,
cmd_target_parse, NULL,
cmd_choose_session_exec, cmd_choose_session_exec
cmd_target_free,
cmd_target_print
}; };
struct cmd_choose_session_data { struct cmd_choose_session_data {
@@ -50,12 +49,12 @@ struct cmd_choose_session_data {
int int
cmd_choose_session_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_choose_session_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct cmd_choose_session_data *cdata; struct cmd_choose_session_data *cdata;
struct winlink *wl; struct winlink *wl;
struct session *s; struct session *s;
struct session_group *sg; struct session_group *sg;
u_int i, idx, cur; u_int idx, sgidx, cur;
char tmp[64]; char tmp[64];
if (ctx->curclient == NULL) { if (ctx->curclient == NULL) {
@@ -63,17 +62,14 @@ cmd_choose_session_exec(struct cmd *self, struct cmd_ctx *ctx)
return (-1); return (-1);
} }
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
return (-1); return (-1);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0) if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
return (0); return (0);
cur = idx = 0; cur = idx = 0;
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { RB_FOREACH(s, sessions, &sessions) {
s = ARRAY_ITEM(&sessions, i);
if (s == NULL)
continue;
if (s == ctx->curclient->session) if (s == ctx->curclient->session)
cur = idx; cur = idx;
idx++; idx++;
@@ -82,19 +78,19 @@ cmd_choose_session_exec(struct cmd *self, struct cmd_ctx *ctx)
if (sg == NULL) if (sg == NULL)
*tmp = '\0'; *tmp = '\0';
else { else {
idx = session_group_index(sg); sgidx = session_group_index(sg);
xsnprintf(tmp, sizeof tmp, " (group %u)", idx); xsnprintf(tmp, sizeof tmp, " (group %u)", sgidx);
} }
window_choose_add(wl->window->active, i, window_choose_add(wl->window->active, s->idx,
"%s: %u windows [%ux%u]%s%s", s->name, "%s: %u windows [%ux%u]%s%s", s->name,
winlink_count(&s->windows), s->sx, s->sy, winlink_count(&s->windows), s->sx, s->sy,
tmp, s->flags & SESSION_UNATTACHED ? "" : " (attached)"); tmp, s->flags & SESSION_UNATTACHED ? "" : " (attached)");
} }
cdata = xmalloc(sizeof *cdata); cdata = xmalloc(sizeof *cdata);
if (data->arg != NULL) if (args->argc != 0)
cdata->template = xstrdup(data->arg); cdata->template = xstrdup(args->argv[0]);
else else
cdata->template = xstrdup("switch-client -t '%%'"); cdata->template = xstrdup("switch-client -t '%%'");
cdata->client = ctx->curclient; cdata->client = ctx->curclient;
@@ -120,9 +116,7 @@ cmd_choose_session_callback(void *data, int idx)
if (cdata->client->flags & CLIENT_DEAD) if (cdata->client->flags & CLIENT_DEAD)
return; return;
if ((u_int) idx > ARRAY_LENGTH(&sessions) - 1) s = session_find_by_index(idx);
return;
s = ARRAY_ITEM(&sessions, idx);
if (s == NULL) if (s == NULL)
return; return;
template = cmd_template_replace(cdata->template, s->name, 1); template = cmd_template_replace(cdata->template, s->name, 1);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-choose-window.c,v 1.20 2009-12-04 22:14:47 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -33,13 +33,12 @@ void cmd_choose_window_free(void *);
const struct cmd_entry cmd_choose_window_entry = { const struct cmd_entry cmd_choose_window_entry = {
"choose-window", NULL, "choose-window", NULL,
"t:", 0, 1,
CMD_TARGET_WINDOW_USAGE " [template]", CMD_TARGET_WINDOW_USAGE " [template]",
CMD_ARG01, "", 0,
cmd_target_init, NULL,
cmd_target_parse, NULL,
cmd_choose_window_exec, cmd_choose_window_exec
cmd_target_free,
cmd_target_print
}; };
struct cmd_choose_window_data { struct cmd_choose_window_data {
@@ -51,13 +50,13 @@ struct cmd_choose_window_data {
int int
cmd_choose_window_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_choose_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct cmd_choose_window_data *cdata; struct cmd_choose_window_data *cdata;
struct session *s; struct session *s;
struct winlink *wl, *wm; struct winlink *wl, *wm;
struct window *w; struct window *w;
u_int idx, cur; u_int idx, cur;
char flag, *title; char *flags, *title;
const char *left, *right; const char *left, *right;
if (ctx->curclient == NULL) { if (ctx->curclient == NULL) {
@@ -66,7 +65,7 @@ cmd_choose_window_exec(struct cmd *self, struct cmd_ctx *ctx)
} }
s = ctx->curclient->session; s = ctx->curclient->session;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
return (-1); return (-1);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0) if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
@@ -80,18 +79,7 @@ cmd_choose_window_exec(struct cmd *self, struct cmd_ctx *ctx)
cur = idx; cur = idx;
idx++; idx++;
flag = ' '; flags = window_printable_flags(s, wm);
if (session_alert_has(s, wm, WINDOW_ACTIVITY))
flag = '#';
else if (session_alert_has(s, wm, WINDOW_BELL))
flag = '!';
else if (session_alert_has(s, wm, WINDOW_CONTENT))
flag = '+';
else if (wm == s->curw)
flag = '*';
else if (wm == TAILQ_FIRST(&s->lastw))
flag = '-';
title = w->active->screen->title; title = w->active->screen->title;
if (wm == wl) if (wm == wl)
title = w->active->base.title; title = w->active->base.title;
@@ -101,14 +89,17 @@ cmd_choose_window_exec(struct cmd *self, struct cmd_ctx *ctx)
left = right = ""; left = right = "";
window_choose_add(wl->window->active, window_choose_add(wl->window->active,
wm->idx, "%3d: %s%c [%ux%u] (%u panes)%s%s%s", wm->idx, "%3d: %s%s [%ux%u] (%u panes%s)%s%s%s",
wm->idx, w->name, flag, w->sx, w->sy, window_count_panes(w), wm->idx, w->name, flags, w->sx, w->sy, window_count_panes(w),
w->active->fd == -1 ? ", dead" : "",
left, title, right); left, title, right);
xfree(flags);
} }
cdata = xmalloc(sizeof *cdata); cdata = xmalloc(sizeof *cdata);
if (data->arg != NULL) if (args->argc != 0)
cdata->template = xstrdup(data->arg); cdata->template = xstrdup(args->argv[0]);
else else
cdata->template = xstrdup("select-window -t '%%'"); cdata->template = xstrdup("select-window -t '%%'");
cdata->session = s; cdata->session = s;
@@ -126,20 +117,19 @@ void
cmd_choose_window_callback(void *data, int idx) cmd_choose_window_callback(void *data, int idx)
{ {
struct cmd_choose_window_data *cdata = data; struct cmd_choose_window_data *cdata = data;
struct session *s = cdata->session;
struct cmd_list *cmdlist; struct cmd_list *cmdlist;
struct cmd_ctx ctx; struct cmd_ctx ctx;
char *target, *template, *cause; char *target, *template, *cause;
if (idx == -1) if (idx == -1)
return; return;
if (!session_alive(s))
return;
if (cdata->client->flags & CLIENT_DEAD) if (cdata->client->flags & CLIENT_DEAD)
return; return;
if (cdata->session->flags & SESSION_DEAD)
return;
if (cdata->client->session != cdata->session)
return;
xasprintf(&target, "%s:%d", cdata->session->name, idx); xasprintf(&target, "%s:%d", s->name, idx);
template = cmd_template_replace(cdata->template, target, 1); template = cmd_template_replace(cdata->template, target, 1);
xfree(target); xfree(target);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-clear-history.c,v 1.8 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,23 +28,22 @@ int cmd_clear_history_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_clear_history_entry = { const struct cmd_entry cmd_clear_history_entry = {
"clear-history", "clearhist", "clear-history", "clearhist",
"t:", 0, 0,
CMD_TARGET_PANE_USAGE, CMD_TARGET_PANE_USAGE,
0, "", 0,
cmd_target_init, NULL,
cmd_target_parse, NULL,
cmd_clear_history_exec, cmd_clear_history_exec
cmd_target_free,
cmd_target_print
}; };
int int
cmd_clear_history_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_clear_history_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct window_pane *wp; struct window_pane *wp;
struct grid *gd; struct grid *gd;
if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL) if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL)
return (-1); return (-1);
gd = wp->base.grid; gd = wp->base.grid;

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-clock-mode.c,v 1.7 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,22 +28,21 @@ int cmd_clock_mode_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_clock_mode_entry = { const struct cmd_entry cmd_clock_mode_entry = {
"clock-mode", NULL, "clock-mode", NULL,
"t:", 0, 0,
CMD_TARGET_PANE_USAGE, CMD_TARGET_PANE_USAGE,
0, "", 0,
cmd_target_init, NULL,
cmd_target_parse, NULL,
cmd_clock_mode_exec, cmd_clock_mode_exec
cmd_target_free,
cmd_target_print
}; };
int int
cmd_clock_mode_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_clock_mode_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct window_pane *wp; struct window_pane *wp;
if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL) if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL)
return (-1); return (-1);
window_pane_set_mode(wp, &window_clock_mode); window_pane_set_mode(wp, &window_clock_mode);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-command-prompt.c,v 1.27 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -20,6 +20,7 @@
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
#include <time.h>
#include "tmux.h" #include "tmux.h"
@@ -27,34 +28,27 @@
* Prompt for command in client. * Prompt for command in client.
*/ */
void cmd_command_prompt_init(struct cmd *, int); void cmd_command_prompt_key_binding(struct cmd *, int);
int cmd_command_prompt_parse(struct cmd *, int, char **, char **); int cmd_command_prompt_check(struct args *);
int cmd_command_prompt_exec(struct cmd *, struct cmd_ctx *); int cmd_command_prompt_exec(struct cmd *, struct cmd_ctx *);
void cmd_command_prompt_free(struct cmd *);
size_t cmd_command_prompt_print(struct cmd *, char *, size_t);
int cmd_command_prompt_callback(void *, const char *); int cmd_command_prompt_callback(void *, const char *);
void cmd_command_prompt_cfree(void *); void cmd_command_prompt_free(void *);
const struct cmd_entry cmd_command_prompt_entry = { const struct cmd_entry cmd_command_prompt_entry = {
"command-prompt", NULL, "command-prompt", NULL,
CMD_TARGET_CLIENT_USAGE " [-p prompts] [template]", "I:p:t:", 0, 1,
0, "", "[-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " [template]",
cmd_command_prompt_init, 0,
cmd_command_prompt_parse, cmd_command_prompt_key_binding,
cmd_command_prompt_exec, NULL,
cmd_command_prompt_free, cmd_command_prompt_exec
cmd_command_prompt_print
};
struct cmd_command_prompt_data {
char *prompts;
char *target;
char *template;
}; };
struct cmd_command_prompt_cdata { struct cmd_command_prompt_cdata {
struct client *c; struct client *c;
char *inputs;
char *next_input;
char *next_prompt; char *next_prompt;
char *prompts; char *prompts;
char *template; char *template;
@@ -62,78 +56,44 @@ struct cmd_command_prompt_cdata {
}; };
void void
cmd_command_prompt_init(struct cmd *self, int key) cmd_command_prompt_key_binding(struct cmd *self, int key)
{ {
struct cmd_command_prompt_data *data;
self->data = data = xmalloc(sizeof *data);
data->prompts = NULL;
data->target = NULL;
data->template = NULL;
switch (key) { switch (key) {
case '$':
self->args = args_create(1, "rename-session '%%'");
args_set(self->args, 'I', "#S");
break;
case ',': case ',':
data->template = xstrdup("rename-window '%%'"); self->args = args_create(1, "rename-window '%%'");
args_set(self->args, 'I', "#W");
break; break;
case '.': case '.':
data->template = xstrdup("move-window -t '%%'"); self->args = args_create(1, "move-window -t '%%'");
break; break;
case 'f': case 'f':
data->template = xstrdup("find-window '%%'"); self->args = args_create(1, "find-window '%%'");
break;
case '\'':
self->args = args_create(1, "select-window -t ':%%'");
args_set(self->args, 'p', "index");
break;
default:
self->args = args_create(0);
break; break;
} }
} }
int
cmd_command_prompt_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_command_prompt_data *data;
int opt;
self->entry->init(self, KEYC_NONE);
data = self->data;
while ((opt = getopt(argc, argv, "p:t:")) != -1) {
switch (opt) {
case 'p':
if (data->prompts == NULL)
data->prompts = xstrdup(optarg);
break;
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 0 && argc != 1)
goto usage;
if (argc == 1)
data->template = xstrdup(argv[0]);
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
self->entry->free(self);
return (-1);
}
int int
cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_command_prompt_data *data = self->data; struct args *args = self->args;
const char *inputs, *prompts;
struct cmd_command_prompt_cdata *cdata; struct cmd_command_prompt_cdata *cdata;
struct client *c; struct client *c;
char *prompt, *ptr; char *prompt, *ptr, *input = NULL;
size_t n; size_t n;
if ((c = cmd_find_client(ctx, data->target)) == NULL) if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL)
return (-1); return (-1);
if (c->prompt_string != NULL) if (c->prompt_string != NULL)
@@ -142,67 +102,47 @@ cmd_command_prompt_exec(struct cmd *self, struct cmd_ctx *ctx)
cdata = xmalloc(sizeof *cdata); cdata = xmalloc(sizeof *cdata);
cdata->c = c; cdata->c = c;
cdata->idx = 1; cdata->idx = 1;
cdata->inputs = NULL;
cdata->next_input = NULL;
cdata->next_prompt = NULL; cdata->next_prompt = NULL;
cdata->prompts = NULL; cdata->prompts = NULL;
cdata->template = NULL; cdata->template = NULL;
if (data->template != NULL) if (args->argc != 0)
cdata->template = xstrdup(data->template); cdata->template = xstrdup(args->argv[0]);
else else
cdata->template = xstrdup("%1"); cdata->template = xstrdup("%1");
if (data->prompts != NULL)
cdata->prompts = xstrdup(data->prompts); if ((prompts = args_get(args, 'p')) != NULL)
else if (data->template != NULL) { cdata->prompts = xstrdup(prompts);
n = strcspn(data->template, " ,"); else if (args->argc != 0) {
xasprintf(&cdata->prompts, "(%.*s) ", (int) n, data->template); n = strcspn(cdata->template, " ,");
xasprintf(&cdata->prompts, "(%.*s) ", (int) n, cdata->template);
} else } else
cdata->prompts = xstrdup(":"); cdata->prompts = xstrdup(":");
/* Get first prompt. */
cdata->next_prompt = cdata->prompts; cdata->next_prompt = cdata->prompts;
ptr = strsep(&cdata->next_prompt, ","); ptr = strsep(&cdata->next_prompt, ",");
if (data->prompts == NULL) if (prompts == NULL)
prompt = xstrdup(ptr); prompt = xstrdup(ptr);
else else
xasprintf(&prompt, "%s ", ptr); xasprintf(&prompt, "%s ", ptr);
status_prompt_set(c, prompt, cmd_command_prompt_callback,
cmd_command_prompt_cfree, cdata, 0); /* Get initial prompt input. */
if ((inputs = args_get(args, 'I')) != NULL) {
cdata->inputs = xstrdup(inputs);
cdata->next_input = cdata->inputs;
input = strsep(&cdata->next_input, ",");
}
status_prompt_set(c, prompt, input, cmd_command_prompt_callback,
cmd_command_prompt_free, cdata, 0);
xfree(prompt); xfree(prompt);
return (0); return (0);
} }
void
cmd_command_prompt_free(struct cmd *self)
{
struct cmd_command_prompt_data *data = self->data;
if (data->prompts != NULL)
xfree(data->prompts);
if (data->target != NULL)
xfree(data->target);
if (data->template != NULL)
xfree(data->template);
xfree(data);
}
size_t
cmd_command_prompt_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_command_prompt_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->prompts != NULL)
off += cmd_prarg(buf + off, len - off, " -p ", data->prompts);
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->template != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->template);
return (off);
}
int int
cmd_command_prompt_callback(void *data, const char *s) cmd_command_prompt_callback(void *data, const char *s)
{ {
@@ -210,24 +150,31 @@ cmd_command_prompt_callback(void *data, const char *s)
struct client *c = cdata->c; struct client *c = cdata->c;
struct cmd_list *cmdlist; struct cmd_list *cmdlist;
struct cmd_ctx ctx; struct cmd_ctx ctx;
char *cause, *newtempl, *prompt, *ptr; char *cause, *new_template, *prompt, *ptr;
char *input = NULL;
if (s == NULL) if (s == NULL)
return (0); return (0);
newtempl = cmd_template_replace(cdata->template, s, cdata->idx); new_template = cmd_template_replace(cdata->template, s, cdata->idx);
xfree(cdata->template); xfree(cdata->template);
cdata->template = newtempl; cdata->template = new_template;
/*
* Check if there are more prompts; if so, get its respective input
* and update the prompt data.
*/
if ((ptr = strsep(&cdata->next_prompt, ",")) != NULL) { if ((ptr = strsep(&cdata->next_prompt, ",")) != NULL) {
xasprintf(&prompt, "%s ", ptr); xasprintf(&prompt, "%s ", ptr);
status_prompt_update(c, prompt); input = strsep(&cdata->next_input, ",");
status_prompt_update(c, prompt, input);
xfree(prompt); xfree(prompt);
cdata->idx++; cdata->idx++;
return (1); return (1);
} }
if (cmd_string_parse(newtempl, &cmdlist, &cause) != 0) { if (cmd_string_parse(new_template, &cmdlist, &cause) != 0) {
if (cause != NULL) { if (cause != NULL) {
*cause = toupper((u_char) *cause); *cause = toupper((u_char) *cause);
status_message_set(c, "%s", cause); status_message_set(c, "%s", cause);
@@ -254,10 +201,12 @@ cmd_command_prompt_callback(void *data, const char *s)
} }
void void
cmd_command_prompt_cfree(void *data) cmd_command_prompt_free(void *data)
{ {
struct cmd_command_prompt_cdata *cdata = data; struct cmd_command_prompt_cdata *cdata = data;
if (cdata->inputs != NULL)
xfree(cdata->inputs);
if (cdata->prompts != NULL) if (cdata->prompts != NULL)
xfree(cdata->prompts); xfree(cdata->prompts);
if (cdata->template != NULL) if (cdata->template != NULL)

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-confirm-before.c,v 1.12 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org> * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -25,21 +25,20 @@
* Asks for confirmation before executing a command. * Asks for confirmation before executing a command.
*/ */
void cmd_confirm_before_key_binding(struct cmd *, int);
int cmd_confirm_before_exec(struct cmd *, struct cmd_ctx *); int cmd_confirm_before_exec(struct cmd *, struct cmd_ctx *);
void cmd_confirm_before_init(struct cmd *, int);
int cmd_confirm_before_callback(void *, const char *); int cmd_confirm_before_callback(void *, const char *);
void cmd_confirm_before_free(void *); void cmd_confirm_before_free(void *);
const struct cmd_entry cmd_confirm_before_entry = { const struct cmd_entry cmd_confirm_before_entry = {
"confirm-before", "confirm", "confirm-before", "confirm",
CMD_TARGET_CLIENT_USAGE " command", "p:t:", 1, 1,
CMD_ARG1, "", "[-p prompt] " CMD_TARGET_CLIENT_USAGE " command",
cmd_confirm_before_init, 0,
cmd_target_parse, cmd_confirm_before_key_binding,
cmd_confirm_before_exec, NULL,
cmd_target_free, cmd_confirm_before_exec
cmd_target_print
}; };
struct cmd_confirm_before_data { struct cmd_confirm_before_data {
@@ -48,19 +47,19 @@ struct cmd_confirm_before_data {
}; };
void void
cmd_confirm_before_init(struct cmd *self, int key) cmd_confirm_before_key_binding(struct cmd *self, int key)
{ {
struct cmd_target_data *data;
cmd_target_init(self, key);
data = self->data;
switch (key) { switch (key) {
case '&': case '&':
data->arg = xstrdup("kill-window"); self->args = args_create(1, "kill-window");
args_set(self->args, 'p', "kill-window #W? (y/n)");
break; break;
case 'x': case 'x':
data->arg = xstrdup("kill-pane"); self->args = args_create(1, "kill-pane");
args_set(self->args, 'p', "kill-pane #P? (y/n)");
break;
default:
self->args = args_create(0);
break; break;
} }
} }
@@ -68,33 +67,37 @@ cmd_confirm_before_init(struct cmd *self, int key)
int int
cmd_confirm_before_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_confirm_before_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct cmd_confirm_before_data *cdata; struct cmd_confirm_before_data *cdata;
struct client *c; struct client *c;
char *buf, *cmd, *ptr; char *cmd, *copy, *new_prompt, *ptr;
const char *prompt;
if (ctx->curclient == NULL) { if (ctx->curclient == NULL) {
ctx->error(ctx, "must be run interactively"); ctx->error(ctx, "must be run interactively");
return (-1); return (-1);
} }
if ((c = cmd_find_client(ctx, data->target)) == NULL) if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL)
return (-1); return (-1);
ptr = xstrdup(data->arg); if ((prompt = args_get(args, 'p')) != NULL)
if ((cmd = strtok(ptr, " \t")) == NULL) xasprintf(&new_prompt, "%s ", prompt);
cmd = ptr; else {
xasprintf(&buf, "Confirm '%s'? (y/n) ", cmd); ptr = copy = xstrdup(args->argv[0]);
xfree(ptr); cmd = strsep(&ptr, " \t");
xasprintf(&new_prompt, "Confirm '%s'? (y/n) ", cmd);
xfree(copy);
}
cdata = xmalloc(sizeof *cdata); cdata = xmalloc(sizeof *cdata);
cdata->cmd = xstrdup(data->arg); cdata->cmd = xstrdup(args->argv[0]);
cdata->c = c; cdata->c = c;
status_prompt_set(cdata->c, buf, status_prompt_set(cdata->c, new_prompt, NULL,
cmd_confirm_before_callback, cmd_confirm_before_free, cdata, cmd_confirm_before_callback, cmd_confirm_before_free, cdata,
PROMPT_SINGLE); PROMPT_SINGLE);
xfree(buf); xfree(new_prompt);
return (1); return (1);
} }

View File

@@ -1,205 +0,0 @@
/* $Id: cmd-copy-buffer.c,v 1.7 2009-11-28 14:50:36 tcunha Exp $ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
*
* 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 <stdlib.h>
#include <string.h>
#include "tmux.h"
/*
* Copies a session paste buffer to another session.
*/
int cmd_copy_buffer_parse(struct cmd *, int, char **, char **);
int cmd_copy_buffer_exec(struct cmd *, struct cmd_ctx *);
void cmd_copy_buffer_free(struct cmd *);
void cmd_copy_buffer_init(struct cmd *, int);
size_t cmd_copy_buffer_print(struct cmd *, char *, size_t);
struct cmd_copy_buffer_data {
char *dst_session;
char *src_session;
int dst_idx;
int src_idx;
};
const struct cmd_entry cmd_copy_buffer_entry = {
"copy-buffer", "copyb",
"[-a src-index] [-b dst-index] [-s src-session] [-t dst-session]",
0, "",
cmd_copy_buffer_init,
cmd_copy_buffer_parse,
cmd_copy_buffer_exec,
cmd_copy_buffer_free,
cmd_copy_buffer_print
};
/* ARGSUSED */
void
cmd_copy_buffer_init(struct cmd *self, unused int arg)
{
struct cmd_copy_buffer_data *data;
self->data = data = xmalloc(sizeof *data);
data->dst_session = NULL;
data->src_session = NULL;
data->dst_idx = -1;
data->src_idx = -1;
}
int
cmd_copy_buffer_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_copy_buffer_data *data;
const char *errstr;
int n, opt;
self->entry->init(self, KEYC_NONE);
data = self->data;
while ((opt = getopt(argc, argv, "a:b:s:t:")) != -1) {
switch (opt) {
case 'a':
if (data->src_idx == -1) {
n = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xasprintf(cause, "buffer %s", errstr);
goto error;
}
data->src_idx = n;
}
break;
case 'b':
if (data->dst_idx == -1) {
n = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xasprintf(cause, "buffer %s", errstr);
goto error;
}
data->dst_idx = n;
}
break;
case 's':
if (data->src_session == NULL)
data->src_session = xstrdup(optarg);
break;
case 't':
if (data->dst_session == NULL)
data->dst_session = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
error:
self->entry->free(self);
return (-1);
}
int
cmd_copy_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_copy_buffer_data *data = self->data;
struct paste_buffer *pb;
struct paste_stack *dst_ps, *src_ps;
u_char *pdata;
struct session *dst_session, *src_session;
u_int limit;
if ((dst_session = cmd_find_session(ctx, data->dst_session)) == NULL ||
(src_session = cmd_find_session(ctx, data->src_session)) == NULL)
return (-1);
dst_ps = &dst_session->buffers;
src_ps = &src_session->buffers;
if (data->src_idx == -1) {
if ((pb = paste_get_top(src_ps)) == NULL) {
ctx->error(ctx, "no buffers");
return (-1);
}
} else {
if ((pb = paste_get_index(src_ps, data->src_idx)) == NULL) {
ctx->error(ctx, "no buffer %d", data->src_idx);
return (-1);
}
}
limit = options_get_number(&dst_session->options, "buffer-limit");
pdata = xmalloc(pb->size);
memcpy(pdata, pb->data, pb->size);
if (data->dst_idx == -1)
paste_add(dst_ps, pdata, pb->size, limit);
else if (paste_replace(dst_ps, data->dst_idx, pdata, pb->size) != 0) {
ctx->error(ctx, "no buffer %d", data->dst_idx);
xfree(pdata);
return (-1);
}
return (0);
}
void
cmd_copy_buffer_free(struct cmd *self)
{
struct cmd_copy_buffer_data *data = self->data;
if (data->dst_session != NULL)
xfree(data->dst_session);
if (data->src_session != NULL)
xfree(data->src_session);
xfree(data);
}
size_t
cmd_copy_buffer_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_copy_buffer_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->src_idx != -1) {
off += xsnprintf(buf + off, len - off, " -a %d",
data->src_idx);
}
if (off < len && data->dst_idx != -1) {
off += xsnprintf(buf + off, len - off, " -b %d",
data->dst_idx);
}
if (off < len && data->src_session != NULL) {
off += cmd_prarg(buf + off, len - off, " -s ",
data->src_session);
}
if (off < len && data->dst_session != NULL) {
off += cmd_prarg(buf + off, len - off, " -t ",
data->dst_session);
}
return (off);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-copy-mode.c,v 1.26 2010-01-05 23:50:22 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,46 +24,40 @@
* Enter copy mode. * Enter copy mode.
*/ */
void cmd_copy_mode_init(struct cmd *, int); void cmd_copy_mode_key_binding(struct cmd *, int);
int cmd_copy_mode_exec(struct cmd *, struct cmd_ctx *); int cmd_copy_mode_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_copy_mode_entry = { const struct cmd_entry cmd_copy_mode_entry = {
"copy-mode", NULL, "copy-mode", NULL,
"t:u", 0, 0,
"[-u] " CMD_TARGET_PANE_USAGE, "[-u] " CMD_TARGET_PANE_USAGE,
0, "u", 0,
cmd_copy_mode_init, cmd_copy_mode_key_binding,
cmd_target_parse, NULL,
cmd_copy_mode_exec, cmd_copy_mode_exec
cmd_target_free,
cmd_target_print
}; };
void void
cmd_copy_mode_init(struct cmd *self, int key) cmd_copy_mode_key_binding(struct cmd *self, int key)
{ {
struct cmd_target_data *data; self->args = args_create(0);
if (key == KEYC_PPAGE)
cmd_target_init(self, key); args_set(self->args, 'u', NULL);
data = self->data;
switch (key) {
case KEYC_PPAGE:
cmd_set_flag(&data->chflags, 'u');
break;
}
} }
int int
cmd_copy_mode_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_copy_mode_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct window_pane *wp; struct window_pane *wp;
if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL) if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL)
return (-1); return (-1);
window_pane_set_mode(wp, &window_copy_mode); if (window_pane_set_mode(wp, &window_copy_mode) != 0)
if (wp->mode == &window_copy_mode && cmd_check_flag(data->chflags, 'u')) return (0);
window_copy_init_from_pane(wp);
if (wp->mode == &window_copy_mode && args_has(self->args, 'u'))
window_copy_pageup(wp); window_copy_pageup(wp);
return (0); return (0);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-delete-buffer.c,v 1.8 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,28 +30,35 @@ int cmd_delete_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_delete_buffer_entry = { const struct cmd_entry cmd_delete_buffer_entry = {
"delete-buffer", "deleteb", "delete-buffer", "deleteb",
CMD_BUFFER_SESSION_USAGE, "b:", 0, 0,
0, "", CMD_BUFFER_USAGE,
cmd_buffer_init, 0,
cmd_buffer_parse, NULL,
cmd_delete_buffer_exec, NULL,
cmd_buffer_free, cmd_delete_buffer_exec
cmd_buffer_print
}; };
int int
cmd_delete_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_delete_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_buffer_data *data = self->data; struct args *args = self->args;
struct session *s; char *cause;
int buffer;
if ((s = cmd_find_session(ctx, data->target)) == NULL) if (!args_has(args, 'b')) {
paste_free_top(&global_buffers);
return (0);
}
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
if (cause != NULL) {
ctx->error(ctx, "buffer %s", cause);
xfree(cause);
return (-1); return (-1);
}
if (data->buffer == -1) if (paste_free_index(&global_buffers, buffer) != 0) {
paste_free_top(&s->buffers); ctx->error(ctx, "no buffer %d", buffer);
else if (paste_free_index(&s->buffers, data->buffer) != 0) {
ctx->error(ctx, "no buffer %d", data->buffer);
return (-1); return (-1);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-detach-client.c,v 1.11 2010-02-08 18:27:34 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,25 +28,45 @@ int cmd_detach_client_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_detach_client_entry = { const struct cmd_entry cmd_detach_client_entry = {
"detach-client", "detach", "detach-client", "detach",
CMD_TARGET_CLIENT_USAGE, "s:t:P", 0, 0,
CMD_READONLY, "", "[-P] [-s target-session] " CMD_TARGET_CLIENT_USAGE,
cmd_target_init, CMD_READONLY,
cmd_target_parse, NULL,
cmd_detach_client_exec, NULL,
cmd_target_free, cmd_detach_client_exec
cmd_target_print
}; };
int int
cmd_detach_client_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_detach_client_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct client *c; struct client *c;
struct session *s;
enum msgtype msgtype;
u_int i;
if ((c = cmd_find_client(ctx, data->target)) == NULL) if (args_has(args, 'P'))
return (-1); msgtype = MSG_DETACHKILL;
else
msgtype = MSG_DETACH;
server_write_client(c, MSG_DETACH, NULL, 0); if (args_has(args, 's')) {
s = cmd_find_session(ctx, args_get(args, 's'), 0);
if (s == NULL)
return (-1);
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c != NULL && c->session == s)
server_write_client(c, msgtype, NULL, 0);
}
} else {
c = cmd_find_client(ctx, args_get(args, 't'));
if (c == NULL)
return (-1);
server_write_client(c, msgtype, NULL, 0);
}
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-display-message.c,v 1.7 2009-11-28 14:39:53 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org> * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -30,33 +30,45 @@ int cmd_display_message_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_display_message_entry = { const struct cmd_entry cmd_display_message_entry = {
"display-message", "display", "display-message", "display",
"[-p] " CMD_TARGET_CLIENT_USAGE " [message]", "c:pt:", 0, 1,
CMD_ARG01, "p", "[-p] [-c target-client] [-t target-pane] [message]",
cmd_target_init, 0,
cmd_target_parse, NULL,
cmd_display_message_exec, NULL,
cmd_target_free, cmd_display_message_exec
cmd_target_print
}; };
int int
cmd_display_message_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_display_message_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct client *c; struct client *c;
struct session *s;
struct winlink *wl;
struct window_pane *wp;
const char *template; const char *template;
char *msg; char *msg;
if ((c = cmd_find_client(ctx, data->target)) == NULL) if ((c = cmd_find_client(ctx, args_get(args, 'c'))) == NULL)
return (-1); return (-1);
if (data->arg == NULL) if (args_has(args, 't') != 0) {
wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp);
if (wl == NULL)
return (-1);
} else {
s = NULL;
wl = NULL;
wp = NULL;
}
if (args->argc == 0)
template = "[#S] #I:#W, current pane #P - (%H:%M %d-%b-%y)"; template = "[#S] #I:#W, current pane #P - (%H:%M %d-%b-%y)";
else else
template = data->arg; template = args->argv[0];
msg = status_replace(c, NULL, template, time(NULL), 0); msg = status_replace(c, s, wl, wp, template, time(NULL), 0);
if (cmd_check_flag(data->chflags, 'p')) if (args_has(self->args, 'p'))
ctx->print(ctx, "%s", msg); ctx->print(ctx, "%s", msg);
else else
status_message_set(c, "%s", msg); status_message_set(c, "%s", msg);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-display-panes.c,v 1.2 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,22 +28,21 @@ int cmd_display_panes_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_display_panes_entry = { const struct cmd_entry cmd_display_panes_entry = {
"display-panes", "displayp", "display-panes", "displayp",
"t:", 0, 0,
CMD_TARGET_CLIENT_USAGE, CMD_TARGET_CLIENT_USAGE,
0, "", 0,
cmd_target_init, NULL,
cmd_target_parse, NULL,
cmd_display_panes_exec, cmd_display_panes_exec
cmd_target_free,
cmd_target_print
}; };
int int
cmd_display_panes_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_display_panes_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct client *c; struct client *c;
if ((c = cmd_find_client(ctx, data->target)) == NULL) if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL)
return (-1); return (-1);
server_set_identify(c); server_set_identify(c);

View File

@@ -1,60 +0,0 @@
/* $Id: cmd-down-pane.c,v 1.14 2010-01-05 23:52:37 tcunha Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Move down a pane.
*/
int cmd_down_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_down_pane_entry = {
"down-pane", "downp",
CMD_TARGET_WINDOW_USAGE,
0, "",
cmd_target_init,
cmd_target_parse,
cmd_down_pane_exec,
cmd_target_free,
cmd_target_print
};
int
cmd_down_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct winlink *wl;
struct window *w;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
w = wl->window;
do {
w->active = TAILQ_NEXT(w->active, entry);
if (w->active == NULL)
w->active = TAILQ_FIRST(&w->panes);
} while (!window_pane_visible(w->active));
server_status_window(wl->window);
server_redraw_window_borders(wl->window);
return (0);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-find-window.c,v 1.14 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,26 +30,26 @@
int cmd_find_window_exec(struct cmd *, struct cmd_ctx *); int cmd_find_window_exec(struct cmd *, struct cmd_ctx *);
void cmd_find_window_callback(void *, int); void cmd_find_window_callback(void *, int);
void cmd_find_window_free(void *);
const struct cmd_entry cmd_find_window_entry = { const struct cmd_entry cmd_find_window_entry = {
"find-window", "findw", "find-window", "findw",
"t:", 1, 1,
CMD_TARGET_WINDOW_USAGE " match-string", CMD_TARGET_WINDOW_USAGE " match-string",
CMD_ARG1, "", 0,
cmd_target_init, NULL,
cmd_target_parse, NULL,
cmd_find_window_exec, cmd_find_window_exec
cmd_target_free,
cmd_target_print
}; };
struct cmd_find_window_data { struct cmd_find_window_data {
u_int session; struct session *session;
}; };
int int
cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct cmd_find_window_data *cdata; struct cmd_find_window_data *cdata;
struct session *s; struct session *s;
struct winlink *wl, *wm; struct winlink *wl, *wm;
@@ -57,7 +57,7 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
struct window_pane *wp; struct window_pane *wp;
ARRAY_DECL(, u_int) list_idx; ARRAY_DECL(, u_int) list_idx;
ARRAY_DECL(, char *) list_ctx; ARRAY_DECL(, char *) list_ctx;
char *sres, *sctx, *searchstr; char *str, *sres, *sctx, *searchstr;
u_int i, line; u_int i, line;
if (ctx->curclient == NULL) { if (ctx->curclient == NULL) {
@@ -66,13 +66,15 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
} }
s = ctx->curclient->session; s = ctx->curclient->session;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
return (-1); return (-1);
str = args->argv[0];
ARRAY_INIT(&list_idx); ARRAY_INIT(&list_idx);
ARRAY_INIT(&list_ctx); ARRAY_INIT(&list_ctx);
xasprintf(&searchstr, "*%s*", data->arg); xasprintf(&searchstr, "*%s*", str);
RB_FOREACH(wm, winlinks, &s->windows) { RB_FOREACH(wm, winlinks, &s->windows) {
i = 0; i = 0;
TAILQ_FOREACH(wp, &wm->window->panes, entry) { TAILQ_FOREACH(wp, &wm->window->panes, entry) {
@@ -81,7 +83,7 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
if (fnmatch(searchstr, wm->window->name, 0) == 0) if (fnmatch(searchstr, wm->window->name, 0) == 0)
sctx = xstrdup(""); sctx = xstrdup("");
else { else {
sres = window_pane_search(wp, data->arg, &line); sres = window_pane_search(wp, str, &line);
if (sres == NULL && if (sres == NULL &&
fnmatch(searchstr, wp->base.title, 0) != 0) fnmatch(searchstr, wp->base.title, 0) != 0)
continue; continue;
@@ -105,7 +107,7 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
xfree(searchstr); xfree(searchstr);
if (ARRAY_LENGTH(&list_idx) == 0) { if (ARRAY_LENGTH(&list_idx) == 0) {
ctx->error(ctx, "no windows matching: %s", data->arg); ctx->error(ctx, "no windows matching: %s", str);
ARRAY_FREE(&list_idx); ARRAY_FREE(&list_idx);
ARRAY_FREE(&list_ctx); ARRAY_FREE(&list_ctx);
return (-1); return (-1);
@@ -134,11 +136,11 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
} }
cdata = xmalloc(sizeof *cdata); cdata = xmalloc(sizeof *cdata);
if (session_index(s, &cdata->session) != 0) cdata->session = s;
fatalx("session not found"); cdata->session->references++;
window_choose_ready( window_choose_ready(wl->window->active,
wl->window->active, 0, cmd_find_window_callback, xfree, cdata); 0, cmd_find_window_callback, cmd_find_window_free, cdata);
out: out:
ARRAY_FREE(&list_idx); ARRAY_FREE(&list_idx);
@@ -151,12 +153,24 @@ void
cmd_find_window_callback(void *data, int idx) cmd_find_window_callback(void *data, int idx)
{ {
struct cmd_find_window_data *cdata = data; struct cmd_find_window_data *cdata = data;
struct session *s; struct session *s = cdata->session;
if (idx != -1 && cdata->session <= ARRAY_LENGTH(&sessions) - 1) { if (idx == -1)
s = ARRAY_ITEM(&sessions, cdata->session); return;
if (s != NULL && session_select(s, idx) == 0) if (!session_alive(s))
server_redraw_session(s); return;
if (session_select(s, idx) == 0) {
server_redraw_session(s);
recalculate_sizes(); recalculate_sizes();
} }
} }
void
cmd_find_window_free(void *data)
{
struct cmd_find_window_data *cdata = data;
cdata->session->references--;
xfree(cdata);
}

View File

@@ -1,423 +0,0 @@
/* $Id: cmd-generic.c,v 1.38 2009-12-04 22:14:47 tcunha Exp $ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <stdlib.h>
#include <string.h>
#include "tmux.h"
int cmd_getopt(int, char **, const char *, const char *);
int cmd_parse_flags(int, const char *, uint64_t *);
size_t cmd_print_flags(char *, size_t, size_t, uint64_t);
int cmd_fill_argument(int, char **, char **, int, char **);
size_t
cmd_prarg(char *buf, size_t len, const char *prefix, char *arg)
{
if (strchr(arg, ' ') != NULL)
return (xsnprintf(buf, len, "%s\"%s\"", prefix, arg));
return (xsnprintf(buf, len, "%s%s", prefix, arg));
}
/* Append two flag strings together and call getopt. */
int
cmd_getopt(int argc, char **argv, const char *flagstr, const char *chflagstr)
{
char tmp[BUFSIZ];
if (strlcpy(tmp, flagstr, sizeof tmp) >= sizeof tmp)
fatalx("strlcpy overflow");
if (strlcat(tmp, chflagstr, sizeof tmp) >= sizeof tmp)
fatalx("strlcat overflow");
return (getopt(argc, argv, tmp));
}
/* Return if flag character is set. */
int
cmd_check_flag(uint64_t chflags, int flag)
{
if (flag >= 'A' && flag <= 'Z')
flag = 26 + flag - 'A';
else if (flag >= 'a' && flag <= 'z')
flag = flag - 'a';
else
return (0);
return ((chflags & (1ULL << flag)) != 0);
}
/* Set flag character. */
void
cmd_set_flag(uint64_t *chflags, int flag)
{
if (flag >= 'A' && flag <= 'Z')
flag = 26 + flag - 'A';
else if (flag >= 'a' && flag <= 'z')
flag = flag - 'a';
else
return;
(*chflags) |= (1ULL << flag);
}
/* If this option is expected, set it in chflags, otherwise return -1. */
int
cmd_parse_flags(int opt, const char *chflagstr, uint64_t *chflags)
{
if (strchr(chflagstr, opt) == NULL)
return (-1);
cmd_set_flag(chflags, opt);
return (0);
}
/* Print the flags present in chflags. */
size_t
cmd_print_flags(char *buf, size_t len, size_t off, uint64_t chflags)
{
u_char ch;
size_t boff = off;
if (chflags == 0)
return (0);
off += xsnprintf(buf + off, len - off, " -");
for (ch = 0; ch < 26; ch++) {
if (cmd_check_flag(chflags, 'a' + ch))
off += xsnprintf(buf + off, len - off, "%c", 'a' + ch);
if (cmd_check_flag(chflags, 'A' + ch))
off += xsnprintf(buf + off, len - off, "%c", 'A' + ch);
}
return (off - boff);
}
int
cmd_fill_argument(int flags, char **arg, char **arg2, int argc, char **argv)
{
*arg = NULL;
*arg2 = NULL;
if (flags & CMD_ARG1) {
if (argc != 1)
return (-1);
*arg = xstrdup(argv[0]);
return (0);
}
if (flags & CMD_ARG01) {
if (argc != 0 && argc != 1)
return (-1);
if (argc == 1)
*arg = xstrdup(argv[0]);
return (0);
}
if (flags & CMD_ARG2) {
if (argc != 2)
return (-1);
*arg = xstrdup(argv[0]);
*arg2 = xstrdup(argv[1]);
return (0);
}
if (flags & CMD_ARG12) {
if (argc != 1 && argc != 2)
return (-1);
*arg = xstrdup(argv[0]);
if (argc == 2)
*arg2 = xstrdup(argv[1]);
return (0);
}
if (argc != 0)
return (-1);
return (0);
}
/* ARGSUSED */
void
cmd_target_init(struct cmd *self, unused int key)
{
struct cmd_target_data *data;
self->data = data = xmalloc(sizeof *data);
data->chflags = 0;
data->target = NULL;
data->arg = NULL;
data->arg2 = NULL;
}
int
cmd_target_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_target_data *data;
const struct cmd_entry *entry = self->entry;
int opt;
/* Don't use the entry version since it may be dependent on key. */
cmd_target_init(self, 0);
data = self->data;
while ((opt = cmd_getopt(argc, argv, "t:", entry->chflags)) != -1) {
if (cmd_parse_flags(opt, entry->chflags, &data->chflags) == 0)
continue;
switch (opt) {
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (cmd_fill_argument(
self->entry->flags, &data->arg, &data->arg2, argc, argv) != 0)
goto usage;
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
self->entry->free(self);
return (-1);
}
void
cmd_target_free(struct cmd *self)
{
struct cmd_target_data *data = self->data;
if (data->target != NULL)
xfree(data->target);
if (data->arg != NULL)
xfree(data->arg);
if (data->arg2 != NULL)
xfree(data->arg2);
xfree(data);
}
size_t
cmd_target_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_target_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
off += cmd_print_flags(buf, len, off, data->chflags);
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->arg != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->arg);
if (off < len && data->arg2 != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->arg2);
return (off);
}
/* ARGSUSED */
void
cmd_srcdst_init(struct cmd *self, unused int key)
{
struct cmd_srcdst_data *data;
self->data = data = xmalloc(sizeof *data);
data->chflags = 0;
data->src = NULL;
data->dst = NULL;
data->arg = NULL;
data->arg2 = NULL;
}
int
cmd_srcdst_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_srcdst_data *data;
const struct cmd_entry *entry = self->entry;
int opt;
cmd_srcdst_init(self, 0);
data = self->data;
while ((opt = cmd_getopt(argc, argv, "s:t:", entry->chflags)) != -1) {
if (cmd_parse_flags(opt, entry->chflags, &data->chflags) == 0)
continue;
switch (opt) {
case 's':
if (data->src == NULL)
data->src = xstrdup(optarg);
break;
case 't':
if (data->dst == NULL)
data->dst = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (cmd_fill_argument(
self->entry->flags, &data->arg, &data->arg2, argc, argv) != 0)
goto usage;
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
self->entry->free(self);
return (-1);
}
void
cmd_srcdst_free(struct cmd *self)
{
struct cmd_srcdst_data *data = self->data;
if (data->src != NULL)
xfree(data->src);
if (data->dst != NULL)
xfree(data->dst);
if (data->arg != NULL)
xfree(data->arg);
if (data->arg2 != NULL)
xfree(data->arg2);
xfree(data);
}
size_t
cmd_srcdst_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_srcdst_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
off += cmd_print_flags(buf, len, off, data->chflags);
if (off < len && data->src != NULL)
off += xsnprintf(buf + off, len - off, " -s %s", data->src);
if (off < len && data->dst != NULL)
off += xsnprintf(buf + off, len - off, " -t %s", data->dst);
if (off < len && data->arg != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->arg);
if (off < len && data->arg2 != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->arg2);
return (off);
}
/* ARGSUSED */
void
cmd_buffer_init(struct cmd *self, unused int key)
{
struct cmd_buffer_data *data;
self->data = data = xmalloc(sizeof *data);
data->chflags = 0;
data->target = NULL;
data->buffer = -1;
data->arg = NULL;
data->arg2 = NULL;
}
int
cmd_buffer_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_buffer_data *data;
const struct cmd_entry *entry = self->entry;
int opt, n;
const char *errstr;
cmd_buffer_init(self, 0);
data = self->data;
while ((opt = cmd_getopt(argc, argv, "b:t:", entry->chflags)) != -1) {
if (cmd_parse_flags(opt, entry->chflags, &data->chflags) == 0)
continue;
switch (opt) {
case 'b':
if (data->buffer == -1) {
n = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr != NULL) {
xasprintf(cause, "buffer %s", errstr);
goto error;
}
data->buffer = n;
}
break;
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (cmd_fill_argument(
self->entry->flags, &data->arg, &data->arg2, argc, argv) != 0)
goto usage;
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
error:
self->entry->free(self);
return (-1);
}
void
cmd_buffer_free(struct cmd *self)
{
struct cmd_buffer_data *data = self->data;
if (data->target != NULL)
xfree(data->target);
if (data->arg != NULL)
xfree(data->arg);
if (data->arg2 != NULL)
xfree(data->arg2);
xfree(data);
}
size_t
cmd_buffer_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_buffer_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
off += cmd_print_flags(buf, len, off, data->chflags);
if (off < len && data->buffer != -1)
off += xsnprintf(buf + off, len - off, " -b %d", data->buffer);
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->arg != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->arg);
if (off < len && data->arg2 != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->arg2);
return (off);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-has-session.c,v 1.15 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,21 +28,20 @@ int cmd_has_session_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_has_session_entry = { const struct cmd_entry cmd_has_session_entry = {
"has-session", "has", "has-session", "has",
"t:", 0, 0,
CMD_TARGET_SESSION_USAGE, CMD_TARGET_SESSION_USAGE,
0, "", 0,
cmd_target_init, NULL,
cmd_target_parse, NULL,
cmd_has_session_exec, cmd_has_session_exec
cmd_target_free,
cmd_target_print
}; };
int int
cmd_has_session_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_has_session_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
if (cmd_find_session(ctx, data->target) == NULL) if (cmd_find_session(ctx, args_get(args, 't'), 0) == NULL)
return (-1); return (-1);
return (0); return (0);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-if-shell.c,v 1.8 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org> * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -25,7 +25,7 @@
#include "tmux.h" #include "tmux.h"
/* /*
* Executes a tmux command if a shell command returns true. * Executes a tmux command if a shell command returns true or false.
*/ */
int cmd_if_shell_exec(struct cmd *, struct cmd_ctx *); int cmd_if_shell_exec(struct cmd *, struct cmd_ctx *);
@@ -35,29 +35,33 @@ void cmd_if_shell_free(void *);
const struct cmd_entry cmd_if_shell_entry = { const struct cmd_entry cmd_if_shell_entry = {
"if-shell", "if", "if-shell", "if",
"shell-command command", "", 2, 3,
CMD_ARG2, "", "shell-command command [command]",
cmd_target_init, 0,
cmd_target_parse, NULL,
cmd_if_shell_exec, NULL,
cmd_target_free, cmd_if_shell_exec
cmd_target_print
}; };
struct cmd_if_shell_data { struct cmd_if_shell_data {
char *cmd; char *cmd_if;
char *cmd_else;
struct cmd_ctx ctx; struct cmd_ctx ctx;
}; };
int int
cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct cmd_if_shell_data *cdata; struct cmd_if_shell_data *cdata;
struct job *job; const char *shellcmd = args->argv[0];
cdata = xmalloc(sizeof *cdata); cdata = xmalloc(sizeof *cdata);
cdata->cmd = xstrdup(data->arg2); cdata->cmd_if = xstrdup(args->argv[1]);
if (args->argc == 3)
cdata->cmd_else = xstrdup(args->argv[2]);
else
cdata->cmd_else = NULL;
memcpy(&cdata->ctx, ctx, sizeof cdata->ctx); memcpy(&cdata->ctx, ctx, sizeof cdata->ctx);
if (ctx->cmdclient != NULL) if (ctx->cmdclient != NULL)
@@ -65,9 +69,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
if (ctx->curclient != NULL) if (ctx->curclient != NULL)
ctx->curclient->references++; ctx->curclient->references++;
job = job_add(NULL, 0, NULL, job_run(shellcmd, cmd_if_shell_callback, cmd_if_shell_free, cdata);
data->arg, cmd_if_shell_callback, cmd_if_shell_free, cdata);
job_run(job);
return (1); /* don't let client exit */ return (1); /* don't let client exit */
} }
@@ -78,12 +80,15 @@ cmd_if_shell_callback(struct job *job)
struct cmd_if_shell_data *cdata = job->data; struct cmd_if_shell_data *cdata = job->data;
struct cmd_ctx *ctx = &cdata->ctx; struct cmd_ctx *ctx = &cdata->ctx;
struct cmd_list *cmdlist; struct cmd_list *cmdlist;
char *cause; char *cause, *cmd;
if (!WIFEXITED(job->status) || WEXITSTATUS(job->status) != 0) if (!WIFEXITED(job->status) || WEXITSTATUS(job->status) != 0) {
return; cmd = cdata->cmd_else;
if (cmd == NULL)
if (cmd_string_parse(cdata->cmd, &cmdlist, &cause) != 0) { return;
} else
cmd = cdata->cmd_if;
if (cmd_string_parse(cmd, &cmdlist, &cause) != 0) {
if (cause != NULL) { if (cause != NULL) {
ctx->error(ctx, "%s", cause); ctx->error(ctx, "%s", cause);
xfree(cause); xfree(cause);
@@ -91,11 +96,7 @@ cmd_if_shell_callback(struct job *job)
return; return;
} }
if (cmd_list_exec(cmdlist, ctx) < 0) { cmd_list_exec(cmdlist, ctx);
cmd_list_free(cmdlist);
return;
}
cmd_list_free(cmdlist); cmd_list_free(cmdlist);
} }
@@ -104,14 +105,18 @@ cmd_if_shell_free(void *data)
{ {
struct cmd_if_shell_data *cdata = data; struct cmd_if_shell_data *cdata = data;
struct cmd_ctx *ctx = &cdata->ctx; struct cmd_ctx *ctx = &cdata->ctx;
struct msg_exit_data exitdata;
if (ctx->cmdclient != NULL) { if (ctx->cmdclient != NULL) {
ctx->cmdclient->references--; ctx->cmdclient->references--;
server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); exitdata.retcode = ctx->cmdclient->retcode;
ctx->cmdclient->flags |= CLIENT_EXIT;
} }
if (ctx->curclient != NULL) if (ctx->curclient != NULL)
ctx->curclient->references--; ctx->curclient->references--;
xfree(cdata->cmd); if (cdata->cmd_else != NULL)
xfree(cdata->cmd_else);
xfree(cdata->cmd_if);
xfree(cdata); xfree(cdata);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-join-pane.c,v 1.2 2010-01-08 16:34:17 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,138 +27,54 @@
* Join a pane into another (like split/swap/kill). * Join a pane into another (like split/swap/kill).
*/ */
int cmd_join_pane_parse(struct cmd *, int, char **, char **); void cmd_join_pane_key_binding(struct cmd *, int);
int cmd_join_pane_exec(struct cmd *, struct cmd_ctx *); int cmd_join_pane_exec(struct cmd *, struct cmd_ctx *);
void cmd_join_pane_free(struct cmd *);
void cmd_join_pane_init(struct cmd *, int);
size_t cmd_join_pane_print(struct cmd *, char *, size_t);
struct cmd_join_pane_data {
char *src;
char *dst;
int flag_detached;
int flag_horizontal;
int percentage;
int size;
};
const struct cmd_entry cmd_join_pane_entry = { const struct cmd_entry cmd_join_pane_entry = {
"join-pane", "joinp", "join-pane", "joinp",
"[-dhv] [-p percentage|-l size] [-t src-pane] [-t dst-pane] [command]", "dhvp:l:s:t:", 0, 0,
0, "", "[-dhv] [-p percentage|-l size] [-s src-pane] [-t dst-pane]",
cmd_join_pane_init, 0,
cmd_join_pane_parse, cmd_join_pane_key_binding,
cmd_join_pane_exec, NULL,
cmd_join_pane_free, cmd_join_pane_exec
cmd_join_pane_print
}; };
void void
cmd_join_pane_init(struct cmd *self, int key) cmd_join_pane_key_binding(struct cmd *self, int key)
{ {
struct cmd_join_pane_data *data;
self->data = data = xmalloc(sizeof *data);
data->src = NULL;
data->dst = NULL;
data->flag_detached = 0;
data->flag_horizontal = 0;
data->percentage = -1;
data->size = -1;
switch (key) { switch (key) {
case '%': case '%':
data->flag_horizontal = 1; self->args = args_create(0);
args_set(self->args, 'h', NULL);
break; break;
case '"': default:
data->flag_horizontal = 0; self->args = args_create(0);
break; break;
} }
} }
int
cmd_join_pane_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_join_pane_data *data;
int opt;
const char *errstr;
self->entry->init(self, KEYC_NONE);
data = self->data;
while ((opt = getopt(argc, argv, "dhl:p:s:t:v")) != -1) {
switch (opt) {
case 'd':
data->flag_detached = 1;
break;
case 'h':
data->flag_horizontal = 1;
break;
case 's':
if (data->src == NULL)
data->src = xstrdup(optarg);
break;
case 't':
if (data->dst == NULL)
data->dst = xstrdup(optarg);
break;
case 'l':
if (data->percentage != -1 || data->size != -1)
break;
data->size = strtonum(optarg, 1, INT_MAX, &errstr);
if (errstr != NULL) {
xasprintf(cause, "size %s", errstr);
goto error;
}
break;
case 'p':
if (data->size != -1 || data->percentage != -1)
break;
data->percentage = strtonum(optarg, 1, 100, &errstr);
if (errstr != NULL) {
xasprintf(cause, "percentage %s", errstr);
goto error;
}
break;
case 'v':
data->flag_horizontal = 0;
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 0)
goto usage;
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
error:
self->entry->free(self);
return (-1);
}
int int
cmd_join_pane_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_join_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_join_pane_data *data = self->data; struct args *args = self->args;
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;
struct window_pane *src_wp, *dst_wp; struct window_pane *src_wp, *dst_wp;
int size; char *cause;
enum layout_type type; int size, percentage, dst_idx;
struct layout_cell *lc; enum layout_type type;
struct layout_cell *lc;
if ((dst_wl = cmd_find_pane(ctx, data->dst, &dst_s, &dst_wp)) == NULL) dst_wl = cmd_find_pane(ctx, args_get(args, 't'), &dst_s, &dst_wp);
if (dst_wl == NULL)
return (-1); return (-1);
dst_w = dst_wl->window; dst_w = dst_wl->window;
dst_idx = dst_wl->idx;
if ((src_wl = cmd_find_pane(ctx, data->src, NULL, &src_wp)) == NULL) src_wl = cmd_find_pane(ctx, args_get(args, 's'), NULL, &src_wp);
if (src_wl == NULL)
return (-1); return (-1);
src_w = src_wl->window; src_w = src_wl->window;
@@ -168,17 +84,28 @@ cmd_join_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
} }
type = LAYOUT_TOPBOTTOM; type = LAYOUT_TOPBOTTOM;
if (data->flag_horizontal) if (args_has(args, 'h'))
type = LAYOUT_LEFTRIGHT; type = LAYOUT_LEFTRIGHT;
size = -1; size = -1;
if (data->size != -1) if (args_has(args, 'l')) {
size = data->size; size = args_strtonum(args, 'l', 0, INT_MAX, &cause);
else if (data->percentage != -1) { if (cause != NULL) {
ctx->error(ctx, "size %s", cause);
xfree(cause);
return (-1);
}
} else if (args_has(args, 'p')) {
percentage = args_strtonum(args, 'p', 0, 100, &cause);
if (cause != NULL) {
ctx->error(ctx, "percentage %s", cause);
xfree(cause);
return (-1);
}
if (type == LAYOUT_TOPBOTTOM) if (type == LAYOUT_TOPBOTTOM)
size = (dst_wp->sy * data->percentage) / 100; size = (dst_wp->sy * percentage) / 100;
else else
size = (dst_wp->sx * data->percentage) / 100; size = (dst_wp->sx * percentage) / 100;
} }
if ((lc = layout_split_pane(dst_wp, type, size)) == NULL) { if ((lc = layout_split_pane(dst_wp, type, size)) == NULL) {
@@ -207,50 +134,12 @@ cmd_join_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
server_redraw_window(src_w); server_redraw_window(src_w);
server_redraw_window(dst_w); server_redraw_window(dst_w);
if (!data->flag_detached) { 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_wl->idx); session_select(dst_s, dst_idx);
server_redraw_session(dst_s); server_redraw_session(dst_s);
} else } else
server_status_session(dst_s); server_status_session(dst_s);
return (0); return (0);
} }
void
cmd_join_pane_free(struct cmd *self)
{
struct cmd_join_pane_data *data = self->data;
if (data->src != NULL)
xfree(data->src);
if (data->dst != NULL)
xfree(data->dst);
xfree(data);
}
size_t
cmd_join_pane_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_join_pane_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->flag_detached)
off += xsnprintf(buf + off, len - off, " -d");
if (off < len && data->flag_horizontal)
off += xsnprintf(buf + off, len - off, " -h");
if (off < len && data->size > 0)
off += xsnprintf(buf + off, len - off, " -l %d", data->size);
if (off < len && data->percentage > 0) {
off += xsnprintf(
buf + off, len - off, " -p %d", data->percentage);
}
if (off < len && data->src != NULL)
off += cmd_prarg(buf + off, len - off, " -s ", data->src);
if (off < len && data->dst != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->dst);
return (off);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-kill-pane.c,v 1.15 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,23 +30,22 @@ int cmd_kill_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_kill_pane_entry = { const struct cmd_entry cmd_kill_pane_entry = {
"kill-pane", "killp", "kill-pane", "killp",
"at:", 0, 0,
"[-a] " CMD_TARGET_PANE_USAGE, "[-a] " CMD_TARGET_PANE_USAGE,
0, "a", 0,
cmd_target_init, NULL,
cmd_target_parse, NULL,
cmd_kill_pane_exec, cmd_kill_pane_exec
cmd_target_free,
cmd_target_print
}; };
int int
cmd_kill_pane_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_kill_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct winlink *wl; struct winlink *wl;
struct window_pane *loopwp, *nextwp, *wp; struct window_pane *loopwp, *nextwp, *wp;
if ((wl = cmd_find_pane(ctx, data->target, NULL, &wp)) == NULL) if ((wl = cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp)) == NULL)
return (-1); return (-1);
if (window_count_panes(wl->window) == 1) { if (window_count_panes(wl->window) == 1) {
@@ -56,7 +55,7 @@ cmd_kill_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
return (0); return (0);
} }
if (cmd_check_flag(data->chflags, 'a')) { if (args_has(self->args, 'a')) {
loopwp = TAILQ_FIRST(&wl->window->panes); loopwp = TAILQ_FIRST(&wl->window->panes);
while (loopwp != NULL) { while (loopwp != NULL) {
nextwp = TAILQ_NEXT(loopwp, entry); nextwp = TAILQ_NEXT(loopwp, entry);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-kill-server.c,v 1.11 2009-11-28 14:50:36 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,13 +31,12 @@ int cmd_kill_server_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_kill_server_entry = { const struct cmd_entry cmd_kill_server_entry = {
"kill-server", NULL, "kill-server", NULL,
"", 0, 0,
"", "",
0, "", 0,
NULL, NULL,
NULL, NULL,
cmd_kill_server_exec, cmd_kill_server_exec
NULL,
NULL
}; };
/* ARGSUSED */ /* ARGSUSED */

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-kill-session.c,v 1.17 2009-12-04 22:14:47 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,35 +31,24 @@ int cmd_kill_session_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_kill_session_entry = { const struct cmd_entry cmd_kill_session_entry = {
"kill-session", NULL, "kill-session", NULL,
"t:", 0, 0,
CMD_TARGET_SESSION_USAGE, CMD_TARGET_SESSION_USAGE,
0, "", 0,
cmd_target_init, NULL,
cmd_target_parse, NULL,
cmd_kill_session_exec, cmd_kill_session_exec
cmd_target_free,
cmd_target_print
}; };
int int
cmd_kill_session_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_kill_session_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct session *s; struct session *s;
struct client *c;
u_int i;
if ((s = cmd_find_session(ctx, data->target)) == NULL) if ((s = cmd_find_session(ctx, args_get(args, 't'), 0)) == NULL)
return (-1); return (-1);
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { server_destroy_session(s);
c = ARRAY_ITEM(&clients, i);
if (c != NULL && c->session == s) {
c->session = NULL;
server_write_client(c, MSG_EXIT, NULL, 0);
}
}
recalculate_sizes();
session_destroy(s); session_destroy(s);
return (0); return (0);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-kill-window.c,v 1.21 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,22 +28,21 @@ int cmd_kill_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_kill_window_entry = { const struct cmd_entry cmd_kill_window_entry = {
"kill-window", "killw", "kill-window", "killw",
"t:", 0, 0,
CMD_TARGET_WINDOW_USAGE, CMD_TARGET_WINDOW_USAGE,
0, "", 0,
cmd_target_init, NULL,
cmd_target_parse, NULL,
cmd_kill_window_exec, cmd_kill_window_exec
cmd_target_free,
cmd_target_print
}; };
int int
cmd_kill_window_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_kill_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct winlink *wl; struct winlink *wl;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
return (-1); return (-1);
server_kill_window(wl->window); server_kill_window(wl->window);

View File

@@ -1,58 +0,0 @@
/* $Id: cmd-last-window.c,v 1.19 2009-11-14 17:56:39 tcunha Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Move to last window.
*/
int cmd_last_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_last_window_entry = {
"last-window", "last",
CMD_TARGET_SESSION_USAGE,
0, "",
cmd_target_init,
cmd_target_parse,
cmd_last_window_exec,
cmd_target_free,
cmd_target_print
};
int
cmd_last_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct session *s;
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
if (session_last(s) == 0)
server_redraw_session(s);
else {
ctx->error(ctx, "no last window");
return (-1);
}
recalculate_sizes();
return (0);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-link-window.c,v 1.36 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,31 +30,30 @@ int cmd_link_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_link_window_entry = { const struct cmd_entry cmd_link_window_entry = {
"link-window", "linkw", "link-window", "linkw",
"dks:t:", 0, 0,
"[-dk] " CMD_SRCDST_WINDOW_USAGE, "[-dk] " CMD_SRCDST_WINDOW_USAGE,
0, "dk", 0,
cmd_srcdst_init, NULL,
cmd_srcdst_parse, NULL,
cmd_link_window_exec, cmd_link_window_exec
cmd_srcdst_free,
cmd_srcdst_print
}; };
int int
cmd_link_window_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_link_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_srcdst_data *data = self->data; struct args *args = self->args;
struct session *src, *dst; struct session *src, *dst;
struct winlink *wl; struct winlink *wl;
char *cause; char *cause;
int idx, kflag, dflag; int idx, kflag, dflag;
if ((wl = cmd_find_window(ctx, data->src, &src)) == NULL) if ((wl = cmd_find_window(ctx, args_get(args, 's'), &src)) == NULL)
return (-1); return (-1);
if ((idx = cmd_find_index(ctx, data->dst, &dst)) == -2) if ((idx = cmd_find_index(ctx, args_get(args, 't'), &dst)) == -2)
return (-1); return (-1);
kflag = cmd_check_flag(data->chflags, 'k'); kflag = args_has(self->args, 'k');
dflag = cmd_check_flag(data->chflags, 'd'); dflag = args_has(self->args, 'd');
if (server_link_window(src, wl, dst, idx, kflag, !dflag, &cause) != 0) { if (server_link_window(src, wl, dst, idx, kflag, !dflag, &cause) != 0) {
ctx->error(ctx, "can't link window: %s", cause); ctx->error(ctx, "can't link window: %s", cause);
xfree(cause); xfree(cause);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-list-buffers.c,v 1.15 2009-12-04 22:14:47 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,48 +30,28 @@ int cmd_list_buffers_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_buffers_entry = { const struct cmd_entry cmd_list_buffers_entry = {
"list-buffers", "lsb", "list-buffers", "lsb",
CMD_TARGET_SESSION_USAGE, "", 0, 0,
0, "", "",
cmd_target_init, 0,
cmd_target_parse, NULL,
cmd_list_buffers_exec, NULL,
cmd_target_free, cmd_list_buffers_exec
cmd_target_print
}; };
/* ARGSUSED */
int int
cmd_list_buffers_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_list_buffers_exec(unused struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data;
struct session *s;
struct paste_buffer *pb; struct paste_buffer *pb;
u_int idx; u_int idx;
char tmp[51 * 4 + 1]; char *tmp;
size_t size, len;
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
idx = 0; idx = 0;
while ((pb = paste_walk_stack(&s->buffers, &idx)) != NULL) { while ((pb = paste_walk_stack(&global_buffers, &idx)) != NULL) {
size = pb->size; tmp = paste_print(pb, 50);
ctx->print(ctx,
/* Translate the first 50 characters. */ "%u: %zu bytes: \"%s\"", idx - 1, pb->size, tmp);
len = size; xfree(tmp);
if (len > 50)
len = 50;
strvisx(tmp, pb->data, len, VIS_OCTAL|VIS_TAB|VIS_NL);
/*
* If the first 50 characters were encoded as a longer string,
* or there is definitely more data, add "...".
*/
if (size > 50 || strlen(tmp) > 50) {
tmp[50 - 3] = '\0';
strlcat(tmp, "...", sizeof tmp);
}
ctx->print(ctx, "%u: %zu bytes: \"%s\"", idx - 1, size, tmp);
} }
return (0); return (0);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-list-clients.c,v 1.20 2009-11-28 14:50:36 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,35 +31,59 @@ int cmd_list_clients_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_clients_entry = { const struct cmd_entry cmd_list_clients_entry = {
"list-clients", "lsc", "list-clients", "lsc",
"", "F:t:", 0, 0,
0, "", "[-F format] " CMD_TARGET_SESSION_USAGE,
CMD_READONLY,
NULL, NULL,
NULL, NULL,
cmd_list_clients_exec, cmd_list_clients_exec
NULL,
NULL
}; };
/* ARGSUSED */ /* ARGSUSED */
int int
cmd_list_clients_exec(unused struct cmd *self, struct cmd_ctx *ctx) cmd_list_clients_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct client *c; struct args *args = self->args;
u_int i; struct client *c;
const char *s_utf8; struct session *s;
struct format_tree *ft;
const char *template;
u_int i;
char *line;
if (args_has(args, 't')) {
s = cmd_find_session(ctx, args_get(args, 't'), 0);
if (s == NULL)
return (-1);
} else
s = NULL;
template = args_get(args, 'F');
if (template == NULL) {
template = "#{client_tty}: #{session_name} "
"[#{client_width}x#{client_height} #{client_termname}]"
"#{?client_utf8, (utf8),}"
"#{?client_readonly, (ro),}";
}
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i); c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session == NULL) if (c == NULL || c->session == NULL)
continue; continue;
if (c->tty.flags & TTY_UTF8) if (s != NULL && s != c->session)
s_utf8 = " (utf8)"; continue;
else
s_utf8 = ""; ft = format_create();
ctx->print(ctx, "%s: %s [%ux%u %s]%s", c->tty.path, format_add(ft, "line", "%u", i);
c->session->name, c->tty.sx, c->tty.sy, format_session(ft, c->session);
c->tty.termname, s_utf8); format_client(ft, c);
line = format_expand(ft, template);
ctx->print(ctx, "%s", line);
xfree(line);
format_free(ft);
} }
return (0); return (0);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-list-commands.c,v 1.7 2009-11-28 14:50:36 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,13 +28,12 @@ int cmd_list_commands_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_commands_entry = { const struct cmd_entry cmd_list_commands_entry = {
"list-commands", "lscm", "list-commands", "lscm",
"", 0, 0,
"", "",
0, "", 0,
NULL, NULL,
NULL, NULL,
cmd_list_commands_exec, cmd_list_commands_exec
NULL,
NULL
}; };
/* ARGSUSED */ /* ARGSUSED */

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-list-keys.c,v 1.24 2009-12-04 22:14:47 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -32,56 +32,67 @@ int cmd_list_keys_table(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_keys_entry = { const struct cmd_entry cmd_list_keys_entry = {
"list-keys", "lsk", "list-keys", "lsk",
"t:", 0, 0,
"[-t key-table]", "[-t key-table]",
0, "", 0,
cmd_target_init, NULL,
cmd_target_parse, NULL,
cmd_list_keys_exec, cmd_list_keys_exec
cmd_target_free,
cmd_target_print
}; };
int int
cmd_list_keys_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_list_keys_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct key_binding *bd; struct key_binding *bd;
const char *key; const char *key;
char tmp[BUFSIZ]; char tmp[BUFSIZ], flags[8];
size_t used; size_t used;
int width, keywidth; int width, keywidth;
if (data->target != NULL) if (args_has(args, 't'))
return (cmd_list_keys_table(self, ctx)); return (cmd_list_keys_table(self, ctx));
width = 0; width = 0;
SPLAY_FOREACH(bd, key_bindings, &key_bindings) {
RB_FOREACH(bd, key_bindings, &key_bindings) {
key = key_string_lookup_key(bd->key & ~KEYC_PREFIX); key = key_string_lookup_key(bd->key & ~KEYC_PREFIX);
if (key == NULL) if (key == NULL)
continue; continue;
keywidth = strlen(key) + 1; keywidth = strlen(key);
if (!(bd->key & KEYC_PREFIX)) if (!(bd->key & KEYC_PREFIX)) {
keywidth += 2; if (bd->can_repeat)
keywidth += 4;
else
keywidth += 3;
} else if (bd->can_repeat)
keywidth += 3;
if (keywidth > width) if (keywidth > width)
width = keywidth; width = keywidth;
} }
SPLAY_FOREACH(bd, key_bindings, &key_bindings) { RB_FOREACH(bd, key_bindings, &key_bindings) {
key = key_string_lookup_key(bd->key & ~KEYC_PREFIX); key = key_string_lookup_key(bd->key & ~KEYC_PREFIX);
if (key == NULL) if (key == NULL)
continue; continue;
used = xsnprintf(tmp, sizeof tmp, "%*s: ", width, key);
*flags = '\0';
if (!(bd->key & KEYC_PREFIX)) {
if (bd->can_repeat)
xsnprintf(flags, sizeof flags, "-rn ");
else
xsnprintf(flags, sizeof flags, "-n ");
} else if (bd->can_repeat)
xsnprintf(flags, sizeof flags, "-r ");
used = xsnprintf(tmp, sizeof tmp, "%s%*s ",
flags, (int) (width - strlen(flags)), key);
if (used >= sizeof tmp) if (used >= sizeof tmp)
continue; continue;
if (!(bd->key & KEYC_PREFIX)) {
used = strlcat(tmp, "(no prefix) ", sizeof tmp);
if (used >= sizeof tmp)
continue;
}
cmd_list_print(bd->cmdlist, tmp + used, (sizeof tmp) - used); cmd_list_print(bd->cmdlist, tmp + used, (sizeof tmp) - used);
ctx->print(ctx, "%s", tmp); ctx->print(ctx, "bind-key %s", tmp);
} }
return (0); return (0);
@@ -90,39 +101,48 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_ctx *ctx)
int int
cmd_list_keys_table(struct cmd *self, struct cmd_ctx *ctx) cmd_list_keys_table(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
const char *tablename;
const struct mode_key_table *mtab; const struct mode_key_table *mtab;
struct mode_key_binding *mbind; struct mode_key_binding *mbind;
const char *key, *cmdstr, *mode; const char *key, *cmdstr, *mode;
int width, keywidth; int width, keywidth, any_mode;
if ((mtab = mode_key_findtable(data->target)) == NULL) { tablename = args_get(args, 't');
ctx->error(ctx, "unknown key table: %s", data->target); if ((mtab = mode_key_findtable(tablename)) == NULL) {
ctx->error(ctx, "unknown key table: %s", tablename);
return (-1); return (-1);
} }
width = 0; width = 0;
SPLAY_FOREACH(mbind, mode_key_tree, mtab->tree) { any_mode = 0;
RB_FOREACH(mbind, mode_key_tree, mtab->tree) {
key = key_string_lookup_key(mbind->key); key = key_string_lookup_key(mbind->key);
if (key == NULL) if (key == NULL)
continue; continue;
keywidth = strlen(key) + 1; if (mbind->mode != 0)
any_mode = 1;
keywidth = strlen(key);
if (keywidth > width) if (keywidth > width)
width = keywidth; width = keywidth;
} }
SPLAY_FOREACH(mbind, mode_key_tree, mtab->tree) { RB_FOREACH(mbind, mode_key_tree, mtab->tree) {
key = key_string_lookup_key(mbind->key); key = key_string_lookup_key(mbind->key);
if (key == NULL) if (key == NULL)
continue; continue;
mode = ""; mode = "";
if (mbind->mode != 0) if (mbind->mode != 0)
mode = "(command mode) "; mode = "c";
cmdstr = mode_key_tostring(mtab->cmdstr, mbind->cmd); cmdstr = mode_key_tostring(mtab->cmdstr, mbind->cmd);
if (cmdstr != NULL) if (cmdstr != NULL) {
ctx->print(ctx, "%*s: %s%s", width, key, mode, cmdstr); ctx->print(ctx, "bind-key -%st %s%s %*s %s",
mode, any_mode && *mode == '\0' ? " " : "",
mtab->name, (int) width, key, cmdstr);
}
} }
return (0); return (0);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-list-panes.c,v 1.4 2009-12-04 22:14:47 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,47 +28,116 @@
int cmd_list_panes_exec(struct cmd *, struct cmd_ctx *); int cmd_list_panes_exec(struct cmd *, struct cmd_ctx *);
void cmd_list_panes_server(struct cmd *, struct cmd_ctx *);
void cmd_list_panes_session(
struct cmd *, struct session *, struct cmd_ctx *, int);
void cmd_list_panes_window(struct cmd *,
struct session *, struct winlink *, struct cmd_ctx *, int);
const struct cmd_entry cmd_list_panes_entry = { const struct cmd_entry cmd_list_panes_entry = {
"list-panes", "lsp", "list-panes", "lsp",
CMD_TARGET_WINDOW_USAGE, "asF:t:", 0, 0,
0, "", "[-as] [-F format] [-t target]",
cmd_target_init, 0,
cmd_target_parse, NULL,
cmd_list_panes_exec, NULL,
cmd_target_free, cmd_list_panes_exec
cmd_target_print
}; };
int int
cmd_list_panes_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_list_panes_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct winlink *wl; struct session *s;
struct window_pane *wp; struct winlink *wl;
struct grid *gd;
struct grid_line *gl;
u_int i, n;
unsigned long long size;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if (args_has(args, 'a'))
return (-1); cmd_list_panes_server(self, ctx);
else if (args_has(args, 's')) {
n = 0; s = cmd_find_session(ctx, args_get(args, 't'), 0);
TAILQ_FOREACH(wp, &wl->window->panes, entry) { if (s == NULL)
gd = wp->base.grid; return (-1);
cmd_list_panes_session(self, s, ctx, 1);
size = 0; } else {
for (i = 0; i < gd->hsize; i++) { wl = cmd_find_window(ctx, args_get(args, 't'), &s);
gl = &gd->linedata[i]; if (wl == NULL)
size += gl->cellsize * sizeof *gl->celldata; return (-1);
size += gl->utf8size * sizeof *gl->utf8data; cmd_list_panes_window(self, s, wl, ctx, 0);
}
size += gd->hsize * sizeof *gd->linedata;
ctx->print(ctx, "%u: [%ux%u] [history %u/%u, %llu bytes]",
n, wp->sx, wp->sy, gd->hsize, gd->hlimit, size);
n++;
} }
return (0); return (0);
} }
void
cmd_list_panes_server(struct cmd *self, struct cmd_ctx *ctx)
{
struct session *s;
RB_FOREACH(s, sessions, &sessions)
cmd_list_panes_session(self, s, ctx, 2);
}
void
cmd_list_panes_session(
struct cmd *self, struct session *s, struct cmd_ctx *ctx, int type)
{
struct winlink *wl;
RB_FOREACH(wl, winlinks, &s->windows)
cmd_list_panes_window(self, s, wl, ctx, type);
}
void
cmd_list_panes_window(struct cmd *self,
struct session *s, struct winlink *wl, struct cmd_ctx *ctx, int type)
{
struct args *args = self->args;
struct window_pane *wp;
u_int n;
struct format_tree *ft;
const char *template;
char *line;
template = args_get(args, 'F');
if (template == NULL) {
switch (type) {
case 0:
template = "#{pane_index}: "
"[#{pane_width}x#{pane_height}] [history "
"#{history_size}/#{history_limit}, "
"#{history_bytes} bytes] #{pane_id}"
"#{?pane_active, (active),}#{?pane_dead, (dead),}";
break;
case 1:
template = "#{window_index}.#{pane_index}: "
"[#{pane_width}x#{pane_height}] [history "
"#{history_size}/#{history_limit}, "
"#{history_bytes} bytes] #{pane_id}"
"#{?pane_active, (active),}#{?pane_dead, (dead),}";
break;
case 2:
template = "#{session_name}:#{window_index}.#{pane_index}: "
"[#{pane_width}x#{pane_height}] [history "
"#{history_size}/#{history_limit}, "
"#{history_bytes} bytes] #{pane_id}"
"#{?pane_active, (active),}#{?pane_dead, (dead),}";
break;
}
}
n = 0;
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
ft = format_create();
format_add(ft, "line", "%u", n);
format_session(ft, s);
format_winlink(ft, s, wl);
format_window_pane(ft, wp);
line = format_expand(ft, template);
ctx->print(ctx, "%s", line);
xfree(line);
format_free(ft);
n++;
}
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-list-sessions.c,v 1.25 2009-11-28 14:50:36 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,45 +30,46 @@
int cmd_list_sessions_exec(struct cmd *, struct cmd_ctx *); int cmd_list_sessions_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_list_sessions_entry = { const struct cmd_entry cmd_list_sessions_entry = {
"list-sessions", "ls", "", "list-sessions", "ls",
0, "", "F:", 0, 0,
"[-F format]",
0,
NULL, NULL,
NULL, NULL,
cmd_list_sessions_exec, cmd_list_sessions_exec
NULL,
NULL
}; };
/* ARGSUSED */
int int
cmd_list_sessions_exec(unused struct cmd *self, struct cmd_ctx *ctx) cmd_list_sessions_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct args *args = self->args;
struct session *s; struct session *s;
struct session_group *sg; u_int n;
char *tim, tmp[64]; struct format_tree *ft;
u_int i, idx; const char *template;
time_t t; char *line;
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { template = args_get(args, 'F');
s = ARRAY_ITEM(&sessions, i); if (template == NULL) {
if (s == NULL) template = "#{session_name}: #{session_windows} windows "
continue; "(created #{session_created_string}) [#{session_width}x"
"#{session_height}]#{?session_grouped, (group ,}"
"#{session_group}#{?session_grouped,),}"
"#{?session_attached, (attached),}";
}
sg = session_group_find(s); n = 0;
if (sg == NULL) RB_FOREACH(s, sessions, &sessions) {
*tmp = '\0'; ft = format_create();
else { format_add(ft, "line", "%u", n);
idx = session_group_index(sg); format_session(ft, s);
xsnprintf(tmp, sizeof tmp, " (group %u)", idx);
}
t = s->creation_time.tv_sec; line = format_expand(ft, template);
tim = ctime(&t); ctx->print(ctx, "%s", line);
*strchr(tim, '\n') = '\0'; xfree(line);
ctx->print(ctx, "%s: %u windows (created %s) [%ux%u]%s%s", format_free(ft);
s->name, winlink_count(&s->windows), tim, s->sx, s->sy, n++;
tmp, s->flags & SESSION_UNATTACHED ? "" : " (attached)");
} }
return (0); return (0);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-list-windows.c,v 1.42 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,31 +28,90 @@
int cmd_list_windows_exec(struct cmd *, struct cmd_ctx *); int cmd_list_windows_exec(struct cmd *, struct cmd_ctx *);
void cmd_list_windows_server(struct cmd *, struct cmd_ctx *);
void cmd_list_windows_session(
struct cmd *, struct session *, struct cmd_ctx *, int);
const struct cmd_entry cmd_list_windows_entry = { const struct cmd_entry cmd_list_windows_entry = {
"list-windows", "lsw", "list-windows", "lsw",
CMD_TARGET_SESSION_USAGE, "aF:t:", 0, 0,
0, "", "[-a] [-F format] " CMD_TARGET_SESSION_USAGE,
cmd_target_init, 0,
cmd_target_parse, NULL,
cmd_list_windows_exec, NULL,
cmd_target_free, cmd_list_windows_exec
cmd_target_print
}; };
int int
cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_list_windows_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct session *s; struct session *s;
struct winlink *wl;
if ((s = cmd_find_session(ctx, data->target)) == NULL) if (args_has(args, 'a'))
return (-1); cmd_list_windows_server(self, ctx);
else {
RB_FOREACH(wl, winlinks, &s->windows) { s = cmd_find_session(ctx, args_get(args, 't'), 0);
ctx->print(ctx, "%d: %s [%ux%u]", if (s == NULL)
wl->idx, wl->window->name, wl->window->sx, wl->window->sy); return (-1);
cmd_list_windows_session(self, s, ctx, 0);
} }
return (0); return (0);
} }
void
cmd_list_windows_server(struct cmd *self, struct cmd_ctx *ctx)
{
struct session *s;
RB_FOREACH(s, sessions, &sessions)
cmd_list_windows_session(self, s, ctx, 1);
}
void
cmd_list_windows_session(
struct cmd *self, struct session *s, struct cmd_ctx *ctx, int type)
{
struct args *args = self->args;
struct winlink *wl;
u_int n;
struct format_tree *ft;
const char *template;
char *line;
template = args_get(args, 'F');
if (template == NULL) {
switch (type) {
case 0:
template = "#{window_index}: "
"#{window_name} "
"[#{window_width}x#{window_height}] "
"[layout #{window_layout}]"
"#{?window_active, (active),}";
break;
case 1:
template = "#{session_name}:#{window_index}: "
"#{window_name} "
"[#{window_width}x#{window_height}] "
"[layout #{window_layout}]"
"#{?window_active, (active),}";
break;
}
}
n = 0;
RB_FOREACH(wl, winlinks, &s->windows) {
ft = format_create();
format_add(ft, "line", "%u", n);
format_session(ft, s);
format_winlink(ft, s, wl);
line = format_expand(ft, template);
ctx->print(ctx, "%s", line);
xfree(line);
format_free(ft);
n++;
}
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-list.c,v 1.7 2010-02-02 23:51:04 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,47 +29,52 @@ cmd_list_parse(int argc, char **argv, char **cause)
struct cmd *cmd; struct cmd *cmd;
int i, lastsplit; int i, lastsplit;
size_t arglen, new_argc; size_t arglen, new_argc;
char **new_argv; char **copy_argv, **new_argv;
copy_argv = cmd_copy_argv(argc, argv);
cmdlist = xmalloc(sizeof *cmdlist); cmdlist = xmalloc(sizeof *cmdlist);
TAILQ_INIT(cmdlist); cmdlist->references = 1;
TAILQ_INIT(&cmdlist->list);
lastsplit = 0; lastsplit = 0;
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
arglen = strlen(argv[i]); arglen = strlen(copy_argv[i]);
if (arglen == 0 || argv[i][arglen - 1] != ';') if (arglen == 0 || copy_argv[i][arglen - 1] != ';')
continue; continue;
argv[i][arglen - 1] = '\0'; copy_argv[i][arglen - 1] = '\0';
if (arglen > 1 && argv[i][arglen - 2] == '\\') { if (arglen > 1 && copy_argv[i][arglen - 2] == '\\') {
argv[i][arglen - 2] = ';'; copy_argv[i][arglen - 2] = ';';
continue; continue;
} }
new_argc = i - lastsplit; new_argc = i - lastsplit;
new_argv = argv + lastsplit; new_argv = copy_argv + lastsplit;
if (arglen != 1) if (arglen != 1)
new_argc++; new_argc++;
cmd = cmd_parse(new_argc, new_argv, cause); cmd = cmd_parse(new_argc, new_argv, cause);
if (cmd == NULL) if (cmd == NULL)
goto bad; goto bad;
TAILQ_INSERT_TAIL(cmdlist, cmd, qentry); TAILQ_INSERT_TAIL(&cmdlist->list, cmd, qentry);
lastsplit = i + 1; lastsplit = i + 1;
} }
if (lastsplit != argc) { if (lastsplit != argc) {
cmd = cmd_parse(argc - lastsplit, argv + lastsplit, cause); cmd = cmd_parse(argc - lastsplit, copy_argv + lastsplit, cause);
if (cmd == NULL) if (cmd == NULL)
goto bad; goto bad;
TAILQ_INSERT_TAIL(cmdlist, cmd, qentry); TAILQ_INSERT_TAIL(&cmdlist->list, cmd, qentry);
} }
cmd_free_argv(argc, copy_argv);
return (cmdlist); return (cmdlist);
bad: bad:
cmd_list_free(cmdlist); cmd_list_free(cmdlist);
cmd_free_argv(argc, copy_argv);
return (NULL); return (NULL);
} }
@@ -80,7 +85,7 @@ cmd_list_exec(struct cmd_list *cmdlist, struct cmd_ctx *ctx)
int n, retval; int n, retval;
retval = 0; retval = 0;
TAILQ_FOREACH(cmd, cmdlist, qentry) { TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
if ((n = cmd_exec(cmd, ctx)) == -1) if ((n = cmd_exec(cmd, ctx)) == -1)
return (-1); return (-1);
@@ -99,6 +104,10 @@ cmd_list_exec(struct cmd_list *cmdlist, struct cmd_ctx *ctx)
if (ctx->curclient == NULL) { if (ctx->curclient == NULL) {
ctx->curclient = ctx->cmdclient; ctx->curclient = ctx->cmdclient;
ctx->cmdclient = NULL; ctx->cmdclient = NULL;
ctx->error = key_bindings_error;
ctx->print = key_bindings_print;
ctx->info = key_bindings_info;
} }
} }
} }
@@ -110,9 +119,12 @@ cmd_list_free(struct cmd_list *cmdlist)
{ {
struct cmd *cmd; struct cmd *cmd;
while (!TAILQ_EMPTY(cmdlist)) { if (--cmdlist->references != 0)
cmd = TAILQ_FIRST(cmdlist); return;
TAILQ_REMOVE(cmdlist, cmd, qentry);
while (!TAILQ_EMPTY(&cmdlist->list)) {
cmd = TAILQ_FIRST(&cmdlist->list);
TAILQ_REMOVE(&cmdlist->list, cmd, qentry);
cmd_free(cmd); cmd_free(cmd);
} }
xfree(cmdlist); xfree(cmdlist);
@@ -125,7 +137,7 @@ cmd_list_print(struct cmd_list *cmdlist, char *buf, size_t len)
size_t off; size_t off;
off = 0; off = 0;
TAILQ_FOREACH(cmd, cmdlist, qentry) { TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
if (off >= len) if (off >= len)
break; break;
off += cmd_print(cmd, buf + off, len - off); off += cmd_print(cmd, buf + off, len - off);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-load-buffer.c,v 1.15 2010-02-26 13:30:07 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org> * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -16,46 +16,99 @@
* 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 <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include "tmux.h" #include "tmux.h"
/* /*
* Loads a session paste buffer from a file. * Loads a paste buffer from a file.
*/ */
int cmd_load_buffer_exec(struct cmd *, struct cmd_ctx *); int cmd_load_buffer_exec(struct cmd *, struct cmd_ctx *);
void cmd_load_buffer_callback(struct client *, void *);
const struct cmd_entry cmd_load_buffer_entry = { const struct cmd_entry cmd_load_buffer_entry = {
"load-buffer", "loadb", "load-buffer", "loadb",
CMD_BUFFER_SESSION_USAGE " path", "b:", 1, 1,
CMD_ARG1, "", CMD_BUFFER_USAGE " path",
cmd_buffer_init, 0,
cmd_buffer_parse, NULL,
cmd_load_buffer_exec, NULL,
cmd_buffer_free, cmd_load_buffer_exec
cmd_buffer_print
}; };
int int
cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_buffer_data *data = self->data; struct args *args = self->args;
struct session *s; struct client *c = ctx->cmdclient;
FILE *f; struct session *s;
char *pdata, *new_pdata; FILE *f;
size_t psize; const char *path, *newpath, *wd;
u_int limit; char *pdata, *new_pdata, *cause;
int ch; size_t psize;
u_int limit;
int ch, buffer;
int *buffer_ptr;
if ((s = cmd_find_session(ctx, data->target)) == NULL) if (!args_has(args, 'b'))
return (-1); buffer = -1;
else {
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
if (cause != NULL) {
ctx->error(ctx, "buffer %s", cause);
xfree(cause);
return (-1);
}
}
if ((f = fopen(data->arg, "rb")) == NULL) { path = args->argv[0];
ctx->error(ctx, "%s: %s", data->arg, strerror(errno)); if (strcmp(path, "-") == 0) {
if (c == NULL) {
ctx->error(ctx, "%s: can't read from stdin", path);
return (-1);
}
if (c->flags & CLIENT_TERMINAL) {
ctx->error(ctx, "%s: stdin is a tty", path);
return (-1);
}
if (c->stdin_fd == -1) {
ctx->error(ctx, "%s: can't read from stdin", path);
return (-1);
}
buffer_ptr = xmalloc(sizeof *buffer_ptr);
*buffer_ptr = buffer;
c->stdin_data = buffer_ptr;
c->stdin_callback = cmd_load_buffer_callback;
c->references++;
bufferevent_enable(c->stdin_event, EV_READ);
return (1);
}
if (c != NULL)
wd = c->cwd;
else if ((s = cmd_current_session(ctx, 0)) != NULL) {
wd = options_get_string(&s->options, "default-path");
if (*wd == '\0')
wd = s->cwd;
} else
wd = NULL;
if (wd != NULL && *wd != '\0') {
newpath = get_full_path(wd, path);
if (newpath != NULL)
path = newpath;
}
if ((f = fopen(path, "rb")) == NULL) {
ctx->error(ctx, "%s: %s", path, strerror(errno));
return (-1); return (-1);
} }
@@ -71,7 +124,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
pdata[psize++] = ch; pdata[psize++] = ch;
} }
if (ferror(f)) { if (ferror(f)) {
ctx->error(ctx, "%s: read error", data->arg); ctx->error(ctx, "%s: read error", path);
goto error; goto error;
} }
if (pdata != NULL) if (pdata != NULL)
@@ -79,14 +132,15 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
fclose(f); fclose(f);
limit = options_get_number(&s->options, "buffer-limit"); limit = options_get_number(&global_options, "buffer-limit");
if (data->buffer == -1) { if (buffer == -1) {
paste_add(&s->buffers, pdata, psize, limit); paste_add(&global_buffers, pdata, psize, limit);
return (0); return (0);
} }
if (paste_replace(&s->buffers, data->buffer, pdata, psize) != 0) { if (paste_replace(&global_buffers, buffer, pdata, psize) != 0) {
ctx->error(ctx, "no buffer %d", data->buffer); ctx->error(ctx, "no buffer %d", buffer);
goto error; xfree(pdata);
return (-1);
} }
return (0); return (0);
@@ -94,6 +148,42 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
error: error:
if (pdata != NULL) if (pdata != NULL)
xfree(pdata); xfree(pdata);
fclose(f); if (f != NULL)
fclose(f);
return (-1); return (-1);
} }
void
cmd_load_buffer_callback(struct client *c, void *data)
{
int *buffer = data;
char *pdata;
size_t psize;
u_int limit;
/*
* Event callback has already checked client is not dead and reduced
* its reference count. But tell it to exit.
*/
c->flags |= CLIENT_EXIT;
psize = EVBUFFER_LENGTH(c->stdin_event->input);
if (psize == 0 || (pdata = malloc(psize + 1)) == NULL) {
xfree(data);
return;
}
bufferevent_read(c->stdin_event, pdata, psize);
pdata[psize] = '\0';
limit = options_get_number(&global_options, "buffer-limit");
if (*buffer == -1)
paste_add(&global_buffers, pdata, psize, limit);
else if (paste_replace(&global_buffers, *buffer, pdata, psize) != 0) {
/* No context so can't use server_client_msg_error. */
evbuffer_add_printf(
c->stderr_event->output, "no buffer %d\n", *buffer);
bufferevent_enable(c->stderr_event, EV_WRITE);
}
xfree(data);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-lock-server.c,v 1.9 2009-11-28 14:50:36 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -25,27 +25,60 @@
#include "tmux.h" #include "tmux.h"
/* /*
* Lock server. * Lock commands.
*/ */
int cmd_lock_server_exec(struct cmd *, struct cmd_ctx *); int cmd_lock_server_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_lock_server_entry = { const struct cmd_entry cmd_lock_server_entry = {
"lock-server", "lock", "lock-server", "lock",
"", 0, 0,
"", "",
0, "", 0,
NULL, NULL,
NULL, NULL,
cmd_lock_server_exec, cmd_lock_server_exec
};
const struct cmd_entry cmd_lock_session_entry = {
"lock-session", "locks",
"t:", 0, 0,
CMD_TARGET_SESSION_USAGE,
0,
NULL, NULL,
NULL, NULL,
cmd_lock_server_exec
};
const struct cmd_entry cmd_lock_client_entry = {
"lock-client", "lockc",
"t:", 0, 0,
CMD_TARGET_CLIENT_USAGE,
0,
NULL,
NULL,
cmd_lock_server_exec
}; };
/* ARGSUSED */ /* ARGSUSED */
int int
cmd_lock_server_exec(unused struct cmd *self, unused struct cmd_ctx *ctx) cmd_lock_server_exec(struct cmd *self, unused struct cmd_ctx *ctx)
{ {
server_lock(); struct args *args = self->args;
struct client *c;
struct session *s;
if (self->entry == &cmd_lock_server_entry)
server_lock();
else if (self->entry == &cmd_lock_session_entry) {
if ((s = cmd_find_session(ctx, args_get(args, 't'), 0)) == NULL)
return (-1);
server_lock_session(s);
} else {
if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL)
return (-1);
server_lock_client(c);
}
recalculate_sizes(); recalculate_sizes();
return (0); return (0);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-move-window.c,v 1.13 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,31 +30,30 @@ int cmd_move_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_move_window_entry = { const struct cmd_entry cmd_move_window_entry = {
"move-window", "movew", "move-window", "movew",
"dks:t:", 0, 0,
"[-dk] " CMD_SRCDST_WINDOW_USAGE, "[-dk] " CMD_SRCDST_WINDOW_USAGE,
0, "dk", 0,
cmd_srcdst_init, NULL,
cmd_srcdst_parse, NULL,
cmd_move_window_exec, cmd_move_window_exec
cmd_srcdst_free,
cmd_srcdst_print
}; };
int int
cmd_move_window_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_move_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_srcdst_data *data = self->data; struct args *args = self->args;
struct session *src, *dst; struct session *src, *dst;
struct winlink *wl; struct winlink *wl;
char *cause; char *cause;
int idx, kflag, dflag; int idx, kflag, dflag;
if ((wl = cmd_find_window(ctx, data->src, &src)) == NULL) if ((wl = cmd_find_window(ctx, args_get(args, 's'), &src)) == NULL)
return (-1); return (-1);
if ((idx = cmd_find_index(ctx, data->dst, &dst)) == -2) if ((idx = cmd_find_index(ctx, args_get(args, 't'), &dst)) == -2)
return (-1); return (-1);
kflag = cmd_check_flag(data->chflags, 'k'); kflag = args_has(self->args, 'k');
dflag = cmd_check_flag(data->chflags, 'd'); dflag = args_has(self->args, 'd');
if (server_link_window(src, wl, dst, idx, kflag, !dflag, &cause) != 0) { if (server_link_window(src, wl, dst, idx, kflag, !dflag, &cause) != 0) {
ctx->error(ctx, "can't move window: %s", cause); ctx->error(ctx, "can't move window: %s", cause);
xfree(cause); xfree(cause);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-new-session.c,v 1.76 2010-02-26 13:28:15 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,8 +18,11 @@
#include <sys/types.h> #include <sys/types.h>
#include <pwd.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <termios.h> #include <termios.h>
#include <unistd.h>
#include "tmux.h" #include "tmux.h"
@@ -27,118 +30,62 @@
* Create a new session and attach to the current terminal unless -d is given. * Create a new session and attach to the current terminal unless -d is given.
*/ */
int cmd_new_session_parse(struct cmd *, int, char **, char **); int cmd_new_session_check(struct args *);
int cmd_new_session_exec(struct cmd *, struct cmd_ctx *); int cmd_new_session_exec(struct cmd *, struct cmd_ctx *);
void cmd_new_session_free(struct cmd *);
void cmd_new_session_init(struct cmd *, int);
size_t cmd_new_session_print(struct cmd *, char *, size_t);
struct cmd_new_session_data {
char *target;
char *newname;
char *winname;
char *cmd;
int flag_detached;
};
const struct cmd_entry cmd_new_session_entry = { const struct cmd_entry cmd_new_session_entry = {
"new-session", "new", "new-session", "new",
"[-d] [-n window-name] [-s session-name] [-t target-session] [command]", "dn:s:t:x:y:", 0, 1,
CMD_STARTSERVER|CMD_CANTNEST|CMD_SENDENVIRON, "", "[-d] [-n window-name] [-s session-name] [-t target-session] "
cmd_new_session_init, "[-x width] [-y height] [command]",
cmd_new_session_parse, CMD_STARTSERVER|CMD_CANTNEST|CMD_SENDENVIRON,
cmd_new_session_exec, NULL,
cmd_new_session_free, cmd_new_session_check,
cmd_new_session_print cmd_new_session_exec
}; };
/* ARGSUSED */
void
cmd_new_session_init(struct cmd *self, unused int arg)
{
struct cmd_new_session_data *data;
self->data = data = xmalloc(sizeof *data);
data->flag_detached = 0;
data->target = NULL;
data->newname = NULL;
data->winname = NULL;
data->cmd = NULL;
}
int int
cmd_new_session_parse(struct cmd *self, int argc, char **argv, char **cause) cmd_new_session_check(struct args *args)
{ {
struct cmd_new_session_data *data; if (args_has(args, 't') && (args->argc != 0 || args_has(args, 'n')))
int opt; return (-1);
self->entry->init(self, KEYC_NONE);
data = self->data;
while ((opt = getopt(argc, argv, "ds:t:n:")) != -1) {
switch (opt) {
case 'd':
data->flag_detached = 1;
break;
case 's':
if (data->newname == NULL)
data->newname = xstrdup(optarg);
break;
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
case 'n':
if (data->winname == NULL)
data->winname = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 0 && argc != 1)
goto usage;
if (data->target != NULL && (argc == 1 || data->winname != NULL))
goto usage;
if (argc == 1)
data->cmd = xstrdup(argv[0]);
return (0); return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
self->entry->free(self);
return (-1);
} }
int int
cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_new_session_data *data = self->data; struct args *args = self->args;
struct session *s, *groupwith; struct session *s, *old_s, *groupwith;
struct window *w; struct window *w;
struct window_pane *wp; struct window_pane *wp;
struct environ env; struct environ env;
struct termios tio, *tiop; struct termios tio, *tiop;
const char *update; struct passwd *pw;
char *overrides, *cmd, *cwd, *cause; const char *newname, *target, *update, *cwd, *errstr;
int detached, idx; char *overrides, *cmd, *cause;
u_int sx, sy, i; int detached, idx;
u_int sx, sy, i;
if (data->newname != NULL && session_find(data->newname) != NULL) { newname = args_get(args, 's');
ctx->error(ctx, "duplicate session: %s", data->newname); if (newname != NULL) {
return (-1); if (!session_check_name(newname)) {
ctx->error(ctx, "bad session name: %s", newname);
return (-1);
}
if (session_find(newname) != NULL) {
ctx->error(ctx, "duplicate session: %s", newname);
return (-1);
}
} }
groupwith = NULL; target = args_get(args, 't');
if (data->target != NULL && if (target != NULL) {
(groupwith = cmd_find_session(ctx, data->target)) == NULL) groupwith = cmd_find_session(ctx, target, 0);
return (-1); if (groupwith == NULL)
return (-1);
} else
groupwith = NULL;
/* /*
* There are three cases: * There are three cases:
@@ -159,7 +106,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
*/ */
/* Set -d if no client. */ /* Set -d if no client. */
detached = data->flag_detached; detached = args_has(args, 'd');
if (ctx->cmdclient == NULL && ctx->curclient == NULL) if (ctx->cmdclient == NULL && ctx->curclient == NULL)
detached = 1; detached = 1;
@@ -198,19 +145,42 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
/* Get the new session working directory. */ /* Get the new session working directory. */
if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL) if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL)
cwd = ctx->cmdclient->cwd; cwd = ctx->cmdclient->cwd;
else else {
cwd = options_get_string(&global_s_options, "default-path"); pw = getpwuid(getuid());
if (pw->pw_dir != NULL && *pw->pw_dir != '\0')
cwd = pw->pw_dir;
else
cwd = "/";
}
/* Find new session size. */ /* Find new session size. */
if (detached) { if (ctx->cmdclient != NULL) {
sx = 80;
sy = 24;
} else if (ctx->cmdclient != NULL) {
sx = ctx->cmdclient->tty.sx; sx = ctx->cmdclient->tty.sx;
sy = ctx->cmdclient->tty.sy; sy = ctx->cmdclient->tty.sy;
} else { } else if (ctx->curclient != NULL) {
sx = ctx->curclient->tty.sx; sx = ctx->curclient->tty.sx;
sy = ctx->curclient->tty.sy; sy = ctx->curclient->tty.sy;
} else {
sx = 80;
sy = 24;
}
if (detached) {
if (args_has(args, 'x')) {
sx = strtonum(
args_get(args, 'x'), 1, USHRT_MAX, &errstr);
if (errstr != NULL) {
ctx->error(ctx, "width %s", errstr);
return (-1);
}
}
if (args_has(args, 'y')) {
sy = strtonum(
args_get(args, 'y'), 1, USHRT_MAX, &errstr);
if (errstr != NULL) {
ctx->error(ctx, "height %s", errstr);
return (-1);
}
}
} }
if (sy > 0 && options_get_number(&global_s_options, "status")) if (sy > 0 && options_get_number(&global_s_options, "status"))
sy--; sy--;
@@ -220,10 +190,10 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
sy = 1; sy = 1;
/* Figure out the command for the new window. */ /* Figure out the command for the new window. */
if (data->target != NULL) if (target != NULL)
cmd = NULL; cmd = NULL;
else if (data->cmd != NULL) else if (args->argc != 0)
cmd = data->cmd; cmd = args->argv[0];
else else
cmd = options_get_string(&global_s_options, "default-command"); cmd = options_get_string(&global_s_options, "default-command");
@@ -235,8 +205,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
/* Create the new session. */ /* Create the new session. */
idx = -1 - options_get_number(&global_s_options, "base-index"); idx = -1 - options_get_number(&global_s_options, "base-index");
s = session_create( s = session_create(newname, cmd, cwd, &env, tiop, idx, sx, sy, &cause);
data->newname, cmd, cwd, &env, tiop, idx, sx, sy, &cause);
if (s == NULL) { if (s == NULL) {
ctx->error(ctx, "create session failed: %s", cause); ctx->error(ctx, "create session failed: %s", cause);
xfree(cause); xfree(cause);
@@ -245,11 +214,11 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
environ_free(&env); environ_free(&env);
/* Set the initial window name if one given. */ /* Set the initial window name if one given. */
if (cmd != NULL && data->winname != NULL) { if (cmd != NULL && args_has(args, 'n')) {
w = s->curw->window; w = s->curw->window;
xfree(w->name); xfree(w->name);
w->name = xstrdup(data->winname); w->name = xstrdup(args_get(args, 'n'));
options_set_number(&w->options, "automatic-rename", 0); options_set_number(&w->options, "automatic-rename", 0);
} }
@@ -271,10 +240,19 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
if (!detached) { if (!detached) {
if (ctx->cmdclient != NULL) { if (ctx->cmdclient != NULL) {
server_write_client(ctx->cmdclient, MSG_READY, NULL, 0); server_write_client(ctx->cmdclient, MSG_READY, NULL, 0);
old_s = ctx->cmdclient->session;
if (old_s != NULL)
ctx->cmdclient->last_session = old_s;
ctx->cmdclient->session = s; ctx->cmdclient->session = s;
session_update_activity(s);
server_redraw_client(ctx->cmdclient); server_redraw_client(ctx->cmdclient);
} else { } else {
old_s = ctx->curclient->session;
if (old_s != NULL)
ctx->curclient->last_session = old_s;
ctx->curclient->session = s; ctx->curclient->session = s;
session_update_activity(s);
server_redraw_client(ctx->curclient); server_redraw_client(ctx->curclient);
} }
} }
@@ -287,10 +265,11 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
*/ */
if (cfg_finished && !ARRAY_EMPTY(&cfg_causes)) { if (cfg_finished && !ARRAY_EMPTY(&cfg_causes)) {
wp = s->curw->window->active; wp = s->curw->window->active;
window_pane_set_mode(wp, &window_more_mode); window_pane_set_mode(wp, &window_copy_mode);
window_copy_init_for_output(wp);
for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) { for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) {
cause = ARRAY_ITEM(&cfg_causes, i); cause = ARRAY_ITEM(&cfg_causes, i);
window_more_add(wp, "%s", cause); window_copy_add(wp, "%s", cause);
xfree(cause); xfree(cause);
} }
ARRAY_FREE(&cfg_causes); ARRAY_FREE(&cfg_causes);
@@ -298,39 +277,3 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
return (!detached); /* 1 means don't tell command client to exit */ return (!detached); /* 1 means don't tell command client to exit */
} }
void
cmd_new_session_free(struct cmd *self)
{
struct cmd_new_session_data *data = self->data;
if (data->newname != NULL)
xfree(data->newname);
if (data->winname != NULL)
xfree(data->winname);
if (data->cmd != NULL)
xfree(data->cmd);
xfree(data);
}
size_t
cmd_new_session_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_new_session_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->flag_detached)
off += xsnprintf(buf + off, len - off, " -d");
if (off < len && data->winname != NULL)
off += cmd_prarg(buf + off, len - off, " -n ", data->winname);
if (off < len && data->newname != NULL)
off += cmd_prarg(buf + off, len - off, " -s ", data->newname);
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->cmd != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->cmd);
return (off);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-new-window.c,v 1.43 2010-01-22 17:28:34 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -26,180 +26,96 @@
* Create a new window. * Create a new window.
*/ */
int cmd_new_window_parse(struct cmd *, int, char **, char **);
int cmd_new_window_exec(struct cmd *, struct cmd_ctx *); int cmd_new_window_exec(struct cmd *, struct cmd_ctx *);
void cmd_new_window_free(struct cmd *);
void cmd_new_window_init(struct cmd *, int);
size_t cmd_new_window_print(struct cmd *, char *, size_t);
struct cmd_new_window_data {
char *target;
char *name;
char *cmd;
int flag_detached;
int flag_kill;
};
const struct cmd_entry cmd_new_window_entry = { const struct cmd_entry cmd_new_window_entry = {
"new-window", "neww", "new-window", "neww",
"[-dk] [-n window-name] [-t target-window] [command]", "adkn:Pt:", 0, 1,
0, "", "[-adk] [-n window-name] [-t target-window] [command]",
cmd_new_window_init, 0,
cmd_new_window_parse, NULL,
cmd_new_window_exec, NULL,
cmd_new_window_free, cmd_new_window_exec
cmd_new_window_print
}; };
/* ARGSUSED */
void
cmd_new_window_init(struct cmd *self, unused int arg)
{
struct cmd_new_window_data *data;
self->data = data = xmalloc(sizeof *data);
data->target = NULL;
data->name = NULL;
data->cmd = NULL;
data->flag_detached = 0;
data->flag_kill = 0;
}
int
cmd_new_window_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_new_window_data *data;
int opt;
self->entry->init(self, KEYC_NONE);
data = self->data;
while ((opt = getopt(argc, argv, "dkt:n:")) != -1) {
switch (opt) {
case 'd':
data->flag_detached = 1;
break;
case 'k':
data->flag_kill = 1;
break;
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
case 'n':
if (data->name == NULL)
data->name = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 0 && argc != 1)
goto usage;
if (argc == 1)
data->cmd = xstrdup(argv[0]);
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
self->entry->free(self);
return (-1);
}
int int
cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_new_window_data *data = self->data; struct args *args = self->args;
struct session *s; struct session *s;
struct winlink *wl; struct winlink *wl;
char *cmd, *cwd, *cause; const char *cmd, *cwd;
int idx; char *cause;
int idx, last, detached;
if (data == NULL) if (args_has(args, 'a')) {
return (0); wl = cmd_find_window(ctx, args_get(args, 't'), &s);
if (wl == NULL)
return (-1);
idx = wl->idx + 1;
if ((idx = cmd_find_index(ctx, data->target, &s)) == -2) /* Find the next free index. */
return (-1); for (last = idx; last < INT_MAX; last++) {
if (winlink_find_by_index(&s->windows, last) == NULL)
break;
}
if (last == INT_MAX) {
ctx->error(ctx, "no free window indexes");
return (-1);
}
/* Move everything from last - 1 to idx up a bit. */
for (; last > idx; last--) {
wl = winlink_find_by_index(&s->windows, last - 1);
server_link_window(s, wl, s, last, 0, 0, NULL);
server_unlink_window(s, wl);
}
} else {
if ((idx = cmd_find_index(ctx, args_get(args, 't'), &s)) == -2)
return (-1);
}
detached = args_has(args, 'd');
wl = NULL; wl = NULL;
if (idx != -1) if (idx != -1)
wl = winlink_find_by_index(&s->windows, idx); wl = winlink_find_by_index(&s->windows, idx);
if (wl != NULL && data->flag_kill) { if (wl != NULL && args_has(args, 'k')) {
/* /*
* Can't use session_detach as it will destroy session if this * Can't use session_detach as it will destroy session if this
* makes it empty. * makes it empty.
*/ */
session_alert_cancel(s, wl); wl->flags &= ~WINLINK_ALERTFLAGS;
winlink_stack_remove(&s->lastw, wl); winlink_stack_remove(&s->lastw, wl);
winlink_remove(&s->windows, wl); winlink_remove(&s->windows, wl);
/* Force select/redraw if current. */ /* Force select/redraw if current. */
if (wl == s->curw) { if (wl == s->curw) {
data->flag_detached = 0; detached = 0;
s->curw = NULL; s->curw = NULL;
} }
} }
cmd = data->cmd; if (args->argc == 0)
if (cmd == NULL)
cmd = options_get_string(&s->options, "default-command"); cmd = options_get_string(&s->options, "default-command");
if (ctx->cmdclient == NULL || ctx->cmdclient->cwd == NULL)
cwd = options_get_string(&s->options, "default-path");
else else
cwd = ctx->cmdclient->cwd; cmd = args->argv[0];
cwd = cmd_get_default_path(ctx);
if (idx == -1) if (idx == -1)
idx = -1 - options_get_number(&s->options, "base-index"); idx = -1 - options_get_number(&s->options, "base-index");
wl = session_new(s, data->name, cmd, cwd, idx, &cause); wl = session_new(s, args_get(args, 'n'), cmd, cwd, idx, &cause);
if (wl == NULL) { if (wl == NULL) {
ctx->error(ctx, "create window failed: %s", cause); ctx->error(ctx, "create window failed: %s", cause);
xfree(cause); xfree(cause);
return (-1); return (-1);
} }
if (!data->flag_detached) { if (!detached) {
session_select(s, wl->idx); session_select(s, wl->idx);
server_redraw_session_group(s); server_redraw_session_group(s);
} else } else
server_status_session_group(s); server_status_session_group(s);
if (args_has(args, 'P'))
ctx->print(ctx, "%s:%u", s->name, wl->idx);
return (0); return (0);
} }
void
cmd_new_window_free(struct cmd *self)
{
struct cmd_new_window_data *data = self->data;
if (data->target != NULL)
xfree(data->target);
if (data->name != NULL)
xfree(data->name);
if (data->cmd != NULL)
xfree(data->cmd);
xfree(data);
}
size_t
cmd_new_window_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_new_window_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->flag_detached)
off += xsnprintf(buf + off, len - off, " -d");
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->name != NULL)
off += cmd_prarg(buf + off, len - off, " -n ", data->name);
if (off < len && data->cmd != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->cmd);
return (off);
}

View File

@@ -1,54 +0,0 @@
/* $Id: cmd-next-layout.c,v 1.6 2009-11-14 17:56:39 tcunha Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Switch window to next layout.
*/
int cmd_next_layout_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_next_layout_entry = {
"next-layout", "nextl",
CMD_TARGET_WINDOW_USAGE,
0, "",
cmd_target_init,
cmd_target_parse,
cmd_next_layout_exec,
cmd_target_free,
cmd_target_print
};
int
cmd_next_layout_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct winlink *wl;
u_int layout;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
layout = layout_set_next(wl->window);
ctx->info(ctx, "arranging in: %s", layout_set_name(layout));
return (0);
}

View File

@@ -1,76 +0,0 @@
/* $Id: cmd-next-window.c,v 1.21 2009-11-14 17:56:39 tcunha Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Move to next window.
*/
void cmd_next_window_init(struct cmd *, int);
int cmd_next_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_next_window_entry = {
"next-window", "next",
"[-a] " CMD_TARGET_SESSION_USAGE,
0, "a",
cmd_next_window_init,
cmd_target_parse,
cmd_next_window_exec,
cmd_target_free,
cmd_target_print
};
void
cmd_next_window_init(struct cmd *self, int key)
{
struct cmd_target_data *data;
cmd_target_init(self, key);
data = self->data;
if (key == ('n' | KEYC_ESCAPE))
cmd_set_flag(&data->chflags, 'a');
}
int
cmd_next_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct session *s;
int activity;
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
activity = 0;
if (cmd_check_flag(data->chflags, 'a'))
activity = 1;
if (session_next(s, activity) == 0)
server_redraw_session(s);
else {
ctx->error(ctx, "no next window");
return (-1);
}
recalculate_sizes();
return (0);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-paste-buffer.c,v 1.24 2009-12-04 22:14:47 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,6 +18,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include "tmux.h" #include "tmux.h"
@@ -27,71 +28,91 @@
*/ */
int cmd_paste_buffer_exec(struct cmd *, struct cmd_ctx *); int cmd_paste_buffer_exec(struct cmd *, struct cmd_ctx *);
void cmd_paste_buffer_lf2cr(struct window_pane *, const char *, size_t);
void cmd_paste_buffer_filter(
struct window_pane *, const char *, size_t, const char *);
const struct cmd_entry cmd_paste_buffer_entry = { const struct cmd_entry cmd_paste_buffer_entry = {
"paste-buffer", "pasteb", "paste-buffer", "pasteb",
"[-dr] " CMD_BUFFER_WINDOW_USAGE, "db:rs:t:", 0, 0,
0, "dr", "[-dr] [-s separator] [-b buffer-index] [-t target-pane]",
cmd_buffer_init, 0,
cmd_buffer_parse, NULL,
cmd_paste_buffer_exec, NULL,
cmd_buffer_free, cmd_paste_buffer_exec
cmd_buffer_print
}; };
int int
cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_buffer_data *data = self->data; struct args *args = self->args;
struct winlink *wl;
struct window_pane *wp; struct window_pane *wp;
struct session *s; struct session *s;
struct paste_buffer *pb; struct paste_buffer *pb;
const char *sepstr;
char *cause;
int buffer;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) if (cmd_find_pane(ctx, args_get(args, 't'), &s, &wp) == NULL)
return (-1); return (-1);
wp = wl->window->active;
if (data->buffer == -1) if (!args_has(args, 'b'))
pb = paste_get_top(&s->buffers); buffer = -1;
else { else {
if ((pb = paste_get_index(&s->buffers, data->buffer)) == NULL) { buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
ctx->error(ctx, "no buffer %d", data->buffer); if (cause != NULL) {
ctx->error(ctx, "buffer %s", cause);
xfree(cause);
return (-1);
}
}
if (buffer == -1)
pb = paste_get_top(&global_buffers);
else {
pb = paste_get_index(&global_buffers, buffer);
if (pb == NULL) {
ctx->error(ctx, "no buffer %d", buffer);
return (-1); return (-1);
} }
} }
if (pb != NULL) { if (pb != NULL) {
/* -r means raw data without LF->CR conversion. */ sepstr = args_get(args, 's');
if (cmd_check_flag(data->chflags, 'r')) if (sepstr == NULL) {
bufferevent_write(wp->event, pb->data, pb->size); if (args_has(args, 'r'))
else sepstr = "\n";
cmd_paste_buffer_lf2cr(wp, pb->data, pb->size); else
sepstr = "\r";
}
cmd_paste_buffer_filter(wp, pb->data, pb->size, sepstr);
} }
/* Delete the buffer if -d. */ /* Delete the buffer if -d. */
if (cmd_check_flag(data->chflags, 'd')) { if (args_has(args, 'd')) {
if (data->buffer == -1) if (buffer == -1)
paste_free_top(&s->buffers); paste_free_top(&global_buffers);
else else
paste_free_index(&s->buffers, data->buffer); paste_free_index(&global_buffers, buffer);
} }
return (0); return (0);
} }
/* Add bytes to a buffer but change every '\n' to '\r'. */ /* Add bytes to a buffer and filter '\n' according to separator. */
void void
cmd_paste_buffer_lf2cr(struct window_pane *wp, const char *data, size_t size) cmd_paste_buffer_filter(
struct window_pane *wp, const char *data, size_t size, const char *sep)
{ {
const char *end = data + size; const char *end = data + size;
const char *lf; const char *lf;
size_t seplen;
seplen = strlen(sep);
while ((lf = memchr(data, '\n', end - data)) != NULL) { while ((lf = memchr(data, '\n', end - data)) != NULL) {
if (lf != data) if (lf != data)
bufferevent_write(wp->event, data, lf - data); bufferevent_write(wp->event, data, lf - data);
bufferevent_write(wp->event, "\r", 1); bufferevent_write(wp->event, sep, seplen);
data = lf + 1; data = lf + 1;
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-pipe-pane.c,v 1.10 2009-12-04 22:14:47 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -22,6 +22,7 @@
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <string.h> #include <string.h>
#include <time.h>
#include <unistd.h> #include <unistd.h>
#include "tmux.h" #include "tmux.h"
@@ -36,24 +37,26 @@ void cmd_pipe_pane_error_callback(struct bufferevent *, short, void *);
const struct cmd_entry cmd_pipe_pane_entry = { const struct cmd_entry cmd_pipe_pane_entry = {
"pipe-pane", "pipep", "pipe-pane", "pipep",
CMD_TARGET_PANE_USAGE "[-o] [command]", "ot:", 0, 1,
CMD_ARG01, "o", "[-o] " CMD_TARGET_PANE_USAGE " [command]",
cmd_target_init, 0,
cmd_target_parse, NULL,
cmd_pipe_pane_exec, NULL,
cmd_target_free, cmd_pipe_pane_exec
cmd_target_print
}; };
int int
cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct client *c;
struct window_pane *wp; struct window_pane *wp;
int old_fd, pipe_fd[2], null_fd, mode; char *command;
int old_fd, pipe_fd[2], null_fd;
if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL) if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL)
return (-1); return (-1);
c = cmd_find_client(ctx, NULL);
/* Destroy the old pipe. */ /* Destroy the old pipe. */
old_fd = wp->pipe_fd; old_fd = wp->pipe_fd;
@@ -64,7 +67,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
} }
/* If no pipe command, that is enough. */ /* If no pipe command, that is enough. */
if (data->arg == NULL || *data->arg == '\0') if (args->argc == 0 || *args->argv[0] == '\0')
return (0); return (0);
/* /*
@@ -73,7 +76,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
* *
* bind ^p pipep -o 'cat >>~/output' * bind ^p pipep -o 'cat >>~/output'
*/ */
if (cmd_check_flag(data->chflags, 'o') && old_fd != -1) if (args_has(self->args, 'o') && old_fd != -1)
return (0); return (0);
/* Open the new pipe. */ /* Open the new pipe. */
@@ -90,7 +93,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
case 0: case 0:
/* Child process. */ /* Child process. */
close(pipe_fd[0]); close(pipe_fd[0]);
server_signal_clear(); clear_signals(1);
if (dup2(pipe_fd[1], STDIN_FILENO) == -1) if (dup2(pipe_fd[1], STDIN_FILENO) == -1)
_exit(1); _exit(1);
@@ -105,7 +108,11 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
if (null_fd != STDOUT_FILENO && null_fd != STDERR_FILENO) if (null_fd != STDOUT_FILENO && null_fd != STDERR_FILENO)
close(null_fd); close(null_fd);
execl(_PATH_BSHELL, "sh", "-c", data->arg, (char *) NULL); closefrom(STDERR_FILENO + 1);
command = status_replace(
c, NULL, NULL, NULL, args->argv[0], time(NULL), 0);
execl(_PATH_BSHELL, "sh", "-c", command, (char *) NULL);
_exit(1); _exit(1);
default: default:
/* Parent process. */ /* Parent process. */
@@ -118,12 +125,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
NULL, NULL, cmd_pipe_pane_error_callback, wp); NULL, NULL, cmd_pipe_pane_error_callback, wp);
bufferevent_enable(wp->pipe_event, EV_WRITE); bufferevent_enable(wp->pipe_event, EV_WRITE);
if ((mode = fcntl(wp->pipe_fd, F_GETFL)) == -1) setblocking(wp->pipe_fd, 0);
fatal("fcntl failed");
if (fcntl(wp->pipe_fd, F_SETFL, mode|O_NONBLOCK) == -1)
fatal("fcntl failed");
if (fcntl(wp->pipe_fd, F_SETFD, FD_CLOEXEC) == -1)
fatal("fcntl failed");
return (0); return (0);
} }
} }

View File

@@ -1,54 +0,0 @@
/* $Id: cmd-previous-layout.c,v 1.6 2009-12-04 22:14:47 tcunha Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Switch window to previous layout.
*/
int cmd_previous_layout_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_previous_layout_entry = {
"previous-layout", "prevl",
CMD_TARGET_WINDOW_USAGE,
0, "",
cmd_target_init,
cmd_target_parse,
cmd_previous_layout_exec,
cmd_target_free,
cmd_target_print
};
int
cmd_previous_layout_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct winlink *wl;
u_int layout;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
layout = layout_set_previous(wl->window);
ctx->info(ctx, "arranging in: %s", layout_set_name(layout));
return (0);
}

View File

@@ -1,76 +0,0 @@
/* $Id: cmd-previous-window.c,v 1.21 2009-11-14 17:56:39 tcunha Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Move to previous window.
*/
void cmd_previous_window_init(struct cmd *, int);
int cmd_previous_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_previous_window_entry = {
"previous-window", "prev",
"[-a] " CMD_TARGET_SESSION_USAGE,
0, "a",
cmd_previous_window_init,
cmd_target_parse,
cmd_previous_window_exec,
cmd_target_free,
cmd_target_print
};
void
cmd_previous_window_init(struct cmd *self, int key)
{
struct cmd_target_data *data;
cmd_target_init(self, key);
data = self->data;
if (key == ('p' | KEYC_ESCAPE))
cmd_set_flag(&data->chflags, 'a');
}
int
cmd_previous_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct session *s;
int activity;
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1);
activity = 0;
if (cmd_check_flag(data->chflags, 'a'))
activity = 1;
if (session_previous(s, activity) == 0)
server_redraw_session(s);
else {
ctx->error(ctx, "no previous window");
return (-1);
}
recalculate_sizes();
return (0);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-refresh-client.c,v 1.11 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,25 +28,28 @@ int cmd_refresh_client_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_refresh_client_entry = { const struct cmd_entry cmd_refresh_client_entry = {
"refresh-client", "refresh", "refresh-client", "refresh",
CMD_TARGET_CLIENT_USAGE, "St:", 0, 0,
0, "", "[-S] " CMD_TARGET_CLIENT_USAGE,
cmd_target_init, 0,
cmd_target_parse, NULL,
cmd_refresh_client_exec, NULL,
cmd_target_free, cmd_refresh_client_exec
cmd_target_print
}; };
int int
cmd_refresh_client_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_refresh_client_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct client *c; struct client *c;
if ((c = cmd_find_client(ctx, data->target)) == NULL) if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL)
return (-1); return (-1);
server_redraw_client(c); if (args_has(args, 'S')) {
status_update_jobs(c);
server_status_client(c);
} else
server_redraw_client(c);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-rename-session.c,v 1.19 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,26 +30,38 @@ int cmd_rename_session_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_rename_session_entry = { const struct cmd_entry cmd_rename_session_entry = {
"rename-session", "rename", "rename-session", "rename",
"t:", 1, 1,
CMD_TARGET_SESSION_USAGE " new-name", CMD_TARGET_SESSION_USAGE " new-name",
CMD_ARG1, "", 0,
cmd_target_init, NULL,
cmd_target_parse, NULL,
cmd_rename_session_exec, cmd_rename_session_exec
cmd_target_free,
cmd_target_print
}; };
int int
cmd_rename_session_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_rename_session_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct session *s; struct session *s;
const char *newname;
if ((s = cmd_find_session(ctx, data->target)) == NULL) newname = args->argv[0];
if (!session_check_name(newname)) {
ctx->error(ctx, "bad session name: %s", newname);
return (-1);
}
if (session_find(newname) != NULL) {
ctx->error(ctx, "duplicate session: %s", newname);
return (-1);
}
if ((s = cmd_find_session(ctx, args_get(args, 't'), 0)) == NULL)
return (-1); return (-1);
RB_REMOVE(sessions, &sessions, s);
xfree(s->name); xfree(s->name);
s->name = xstrdup(data->arg); s->name = xstrdup(newname);
RB_INSERT(sessions, &sessions, s);
server_status_session(s); server_status_session(s);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-rename-window.c,v 1.31 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,27 +30,26 @@ int cmd_rename_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_rename_window_entry = { const struct cmd_entry cmd_rename_window_entry = {
"rename-window", "renamew", "rename-window", "renamew",
"t:", 1, 1,
CMD_TARGET_WINDOW_USAGE " new-name", CMD_TARGET_WINDOW_USAGE " new-name",
CMD_ARG1, "", 0,
cmd_target_init, NULL,
cmd_target_parse, NULL,
cmd_rename_window_exec, cmd_rename_window_exec
cmd_target_free,
cmd_target_print
}; };
int int
cmd_rename_window_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_rename_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct session *s; struct session *s;
struct winlink *wl; struct winlink *wl;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) if ((wl = cmd_find_window(ctx, args_get(args, 't'), &s)) == NULL)
return (-1); return (-1);
xfree(wl->window->name); xfree(wl->window->name);
wl->window->name = xstrdup(data->arg); wl->window->name = xstrdup(args->argv[0]);
options_set_number(&wl->window->options, "automatic-rename", 0); options_set_number(&wl->window->options, "automatic-rename", 0);
server_status_window(wl->window); server_status_window(wl->window);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-resize-pane.c,v 1.14 2009-12-04 22:14:47 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -26,84 +26,90 @@
* Increase or decrease pane size. * Increase or decrease pane size.
*/ */
void cmd_resize_pane_init(struct cmd *, int); void cmd_resize_pane_key_binding(struct cmd *, int);
int cmd_resize_pane_exec(struct cmd *, struct cmd_ctx *); int cmd_resize_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_resize_pane_entry = { const struct cmd_entry cmd_resize_pane_entry = {
"resize-pane", "resizep", "resize-pane", "resizep",
"DLRt:U", 0, 1,
"[-DLRU] " CMD_TARGET_PANE_USAGE " [adjustment]", "[-DLRU] " CMD_TARGET_PANE_USAGE " [adjustment]",
CMD_ARG01, "DLRU", 0,
cmd_resize_pane_init, cmd_resize_pane_key_binding,
cmd_target_parse, NULL,
cmd_resize_pane_exec, cmd_resize_pane_exec
cmd_target_free,
cmd_target_print
}; };
void void
cmd_resize_pane_init(struct cmd *self, int key) cmd_resize_pane_key_binding(struct cmd *self, int key)
{ {
struct cmd_target_data *data; switch (key) {
case KEYC_UP | KEYC_CTRL:
cmd_target_init(self, key); self->args = args_create(0);
data = self->data; args_set(self->args, 'U', NULL);
break;
if (key == (KEYC_UP | KEYC_CTRL)) case KEYC_DOWN | KEYC_CTRL:
cmd_set_flag(&data->chflags, 'U'); self->args = args_create(0);
if (key == (KEYC_DOWN | KEYC_CTRL)) args_set(self->args, 'D', NULL);
cmd_set_flag(&data->chflags, 'D'); break;
if (key == (KEYC_LEFT | KEYC_CTRL)) case KEYC_LEFT | KEYC_CTRL:
cmd_set_flag(&data->chflags, 'L'); self->args = args_create(0);
if (key == (KEYC_RIGHT | KEYC_CTRL)) args_set(self->args, 'L', NULL);
cmd_set_flag(&data->chflags, 'R'); break;
case KEYC_RIGHT | KEYC_CTRL:
if (key == (KEYC_UP | KEYC_ESCAPE)) { self->args = args_create(0);
cmd_set_flag(&data->chflags, 'U'); args_set(self->args, 'R', NULL);
data->arg = xstrdup("5"); break;
} case KEYC_UP | KEYC_ESCAPE:
if (key == (KEYC_DOWN | KEYC_ESCAPE)) { self->args = args_create(1, "5");
cmd_set_flag(&data->chflags, 'D'); args_set(self->args, 'U', NULL);
data->arg = xstrdup("5"); break;
} case KEYC_DOWN | KEYC_ESCAPE:
if (key == (KEYC_LEFT | KEYC_ESCAPE)) { self->args = args_create(1, "5");
cmd_set_flag(&data->chflags, 'L'); args_set(self->args, 'D', NULL);
data->arg = xstrdup("5"); break;
} case KEYC_LEFT | KEYC_ESCAPE:
if (key == (KEYC_RIGHT | KEYC_ESCAPE)) { self->args = args_create(1, "5");
cmd_set_flag(&data->chflags, 'R'); args_set(self->args, 'L', NULL);
data->arg = xstrdup("5"); break;
case KEYC_RIGHT | KEYC_ESCAPE:
self->args = args_create(1, "5");
args_set(self->args, 'R', NULL);
break;
default:
self->args = args_create(0);
break;
} }
} }
int int
cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct winlink *wl; struct winlink *wl;
const char *errstr; const char *errstr;
struct window_pane *wp; struct window_pane *wp;
u_int adjust; u_int adjust;
if ((wl = cmd_find_pane(ctx, data->target, NULL, &wp)) == NULL) if ((wl = cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp)) == NULL)
return (-1); return (-1);
if (data->arg == NULL) if (args->argc == 0)
adjust = 1; adjust = 1;
else { else {
adjust = strtonum(data->arg, 1, INT_MAX, &errstr); adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr);
if (errstr != NULL) { if (errstr != NULL) {
ctx->error(ctx, "adjustment %s: %s", errstr, data->arg); ctx->error(ctx, "adjustment %s", errstr);
return (-1); return (-1);
} }
} }
if (cmd_check_flag(data->chflags, 'L')) if (args_has(self->args, 'L'))
layout_resize_pane(wp, LAYOUT_LEFTRIGHT, -adjust); layout_resize_pane(wp, LAYOUT_LEFTRIGHT, -adjust);
else if (cmd_check_flag(data->chflags, 'R')) else if (args_has(self->args, 'R'))
layout_resize_pane(wp, LAYOUT_LEFTRIGHT, adjust); layout_resize_pane(wp, LAYOUT_LEFTRIGHT, adjust);
else if (cmd_check_flag(data->chflags, 'U')) else if (args_has(self->args, 'U'))
layout_resize_pane(wp, LAYOUT_TOPBOTTOM, -adjust); layout_resize_pane(wp, LAYOUT_TOPBOTTOM, -adjust);
else if (cmd_check_flag(data->chflags, 'D')) else if (args_has(self->args, 'D'))
layout_resize_pane(wp, LAYOUT_TOPBOTTOM, adjust); layout_resize_pane(wp, LAYOUT_TOPBOTTOM, adjust);
server_redraw_window(wl->window); server_redraw_window(wl->window);

91
cmd-respawn-pane.c Normal file
View File

@@ -0,0 +1,91 @@
/* $Id$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2011 Marcel P. Partap <mpartap@gmx.net>
*
* 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 <unistd.h>
#include "tmux.h"
/*
* Respawn a pane (restart the command). Kill existing if -k given.
*/
int cmd_respawn_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_respawn_pane_entry = {
"respawn-pane", "respawnp",
"kt:", 0, 1,
"[-k] " CMD_TARGET_PANE_USAGE " [command]",
0,
NULL,
NULL,
cmd_respawn_pane_exec
};
int
cmd_respawn_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct args *args = self->args;
struct winlink *wl;
struct window *w;
struct window_pane *wp;
struct session *s;
struct environ env;
const char *cmd;
char *cause;
u_int idx;
if ((wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp)) == NULL)
return (-1);
w = wl->window;
if (!args_has(self->args, 'k') && wp->fd != -1) {
if (window_pane_index(wp, &idx) != 0)
fatalx("index not found");
ctx->error(ctx, "pane still active: %s:%u.%u",
s->name, wl->idx, idx);
return (-1);
}
environ_init(&env);
environ_copy(&global_environ, &env);
environ_copy(&s->environ, &env);
server_fill_environ(s, &env);
window_pane_reset_mode(wp);
screen_reinit(&wp->base);
input_init(wp);
if (args->argc != 0)
cmd = args->argv[0];
else
cmd = NULL;
if (window_pane_spawn(wp, cmd, NULL, NULL, &env, s->tio, &cause) != 0) {
ctx->error(ctx, "respawn pane failed: %s", cause);
xfree(cause);
environ_free(&env);
return (-1);
}
wp->flags |= PANE_REDRAW;
server_status_window(w);
environ_free(&env);
return (0);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-respawn-window.c,v 1.25 2009-12-04 22:14:47 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,31 +30,31 @@ int cmd_respawn_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_respawn_window_entry = { const struct cmd_entry cmd_respawn_window_entry = {
"respawn-window", "respawnw", "respawn-window", "respawnw",
"kt:", 0, 1,
"[-k] " CMD_TARGET_WINDOW_USAGE " [command]", "[-k] " CMD_TARGET_WINDOW_USAGE " [command]",
CMD_ARG01, "k", 0,
cmd_target_init, NULL,
cmd_target_parse, NULL,
cmd_respawn_window_exec, cmd_respawn_window_exec
cmd_target_free,
cmd_target_print
}; };
int int
cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct winlink *wl; struct winlink *wl;
struct window *w; struct window *w;
struct window_pane *wp; struct window_pane *wp;
struct session *s; struct session *s;
struct environ env; struct environ env;
const char *cmd;
char *cause; char *cause;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) if ((wl = cmd_find_window(ctx, args_get(args, 't'), &s)) == NULL)
return (-1); return (-1);
w = wl->window; w = wl->window;
if (!cmd_check_flag(data->chflags, 'k')) { if (!args_has(self->args, 'k')) {
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->fd == -1) if (wp->fd == -1)
continue; continue;
@@ -75,8 +75,11 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
window_destroy_panes(w); window_destroy_panes(w);
TAILQ_INSERT_HEAD(&w->panes, wp, entry); TAILQ_INSERT_HEAD(&w->panes, wp, entry);
window_pane_resize(wp, w->sx, w->sy); window_pane_resize(wp, w->sx, w->sy);
if (window_pane_spawn( if (args->argc != 0)
wp, data->arg, NULL, NULL, &env, s->tio, &cause) != 0) { cmd = args->argv[0];
else
cmd = NULL;
if (window_pane_spawn(wp, cmd, NULL, NULL, &env, s->tio, &cause) != 0) {
ctx->error(ctx, "respawn window failed: %s", cause); ctx->error(ctx, "respawn window failed: %s", cause);
xfree(cause); xfree(cause);
environ_free(&env); environ_free(&env);
@@ -84,7 +87,9 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
return (-1); return (-1);
} }
layout_init(w); layout_init(w);
window_pane_reset_mode(wp);
screen_reinit(&wp->base); screen_reinit(&wp->base);
input_init(wp);
window_set_active_pane(w, wp); window_set_active_pane(w, wp);
recalculate_sizes(); recalculate_sizes();

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-rotate-window.c,v 1.10 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,47 +24,42 @@
* Rotate the panes in a window. * Rotate the panes in a window.
*/ */
void cmd_rotate_window_init(struct cmd *, int); void cmd_rotate_window_key_binding(struct cmd *, int);
int cmd_rotate_window_exec(struct cmd *, struct cmd_ctx *); int cmd_rotate_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_rotate_window_entry = { const struct cmd_entry cmd_rotate_window_entry = {
"rotate-window", "rotatew", "rotate-window", "rotatew",
"Dt:U", 0, 0,
"[-DU] " CMD_TARGET_WINDOW_USAGE, "[-DU] " CMD_TARGET_WINDOW_USAGE,
0, "DU", 0,
cmd_rotate_window_init, cmd_rotate_window_key_binding,
cmd_target_parse, NULL,
cmd_rotate_window_exec, cmd_rotate_window_exec
cmd_target_free,
cmd_target_print
}; };
void void
cmd_rotate_window_init(struct cmd *self, int key) cmd_rotate_window_key_binding(struct cmd *self, int key)
{ {
struct cmd_target_data *data; self->args = args_create(0);
cmd_target_init(self, key);
data = self->data;
if (key == ('o' | KEYC_ESCAPE)) if (key == ('o' | KEYC_ESCAPE))
cmd_set_flag(&data->chflags, 'D'); args_set(self->args, 'D', NULL);
} }
int int
cmd_rotate_window_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_rotate_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct winlink *wl; struct winlink *wl;
struct window *w; struct window *w;
struct window_pane *wp, *wp2; struct window_pane *wp, *wp2;
struct layout_cell *lc; struct layout_cell *lc;
u_int sx, sy, xoff, yoff; u_int sx, sy, xoff, yoff;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
return (-1); return (-1);
w = wl->window; w = wl->window;
if (cmd_check_flag(data->chflags, 'D')) { if (args_has(self->args, 'D')) {
wp = TAILQ_LAST(&w->panes, window_panes); wp = TAILQ_LAST(&w->panes, window_panes);
TAILQ_REMOVE(&w->panes, wp, entry); TAILQ_REMOVE(&w->panes, wp, entry);
TAILQ_INSERT_HEAD(&w->panes, wp, entry); TAILQ_INSERT_HEAD(&w->panes, wp, entry);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-run-shell.c,v 1.6 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org> * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -35,13 +35,12 @@ void cmd_run_shell_free(void *);
const struct cmd_entry cmd_run_shell_entry = { const struct cmd_entry cmd_run_shell_entry = {
"run-shell", "run", "run-shell", "run",
"", 1, 1,
"command", "command",
CMD_ARG1, "", 0,
cmd_target_init, NULL,
cmd_target_parse, NULL,
cmd_run_shell_exec, cmd_run_shell_exec
cmd_target_free,
cmd_target_print
}; };
struct cmd_run_shell_data { struct cmd_run_shell_data {
@@ -52,12 +51,12 @@ struct cmd_run_shell_data {
int int
cmd_run_shell_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_run_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct cmd_run_shell_data *cdata; struct cmd_run_shell_data *cdata;
struct job *job; const char *shellcmd = args->argv[0];
cdata = xmalloc(sizeof *cdata); cdata = xmalloc(sizeof *cdata);
cdata->cmd = xstrdup(data->arg); cdata->cmd = xstrdup(args->argv[0]);
memcpy(&cdata->ctx, ctx, sizeof cdata->ctx); memcpy(&cdata->ctx, ctx, sizeof cdata->ctx);
if (ctx->cmdclient != NULL) if (ctx->cmdclient != NULL)
@@ -65,9 +64,7 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
if (ctx->curclient != NULL) if (ctx->curclient != NULL)
ctx->curclient->references++; ctx->curclient->references++;
job = job_add(NULL, 0, NULL, job_run(shellcmd, cmd_run_shell_callback, cmd_run_shell_free, cdata);
data->arg, cmd_run_shell_callback, cmd_run_shell_free, cdata);
job_run(job);
return (1); /* don't let client exit */ return (1); /* don't let client exit */
} }
@@ -82,6 +79,11 @@ cmd_run_shell_callback(struct job *job)
int retcode; int retcode;
u_int lines; u_int lines;
if (ctx->cmdclient != NULL && ctx->cmdclient->flags & CLIENT_DEAD)
return;
if (ctx->curclient != NULL && ctx->curclient->flags & CLIENT_DEAD)
return;
lines = 0; lines = 0;
do { do {
if ((line = evbuffer_readline(job->event->input)) != NULL) { if ((line = evbuffer_readline(job->event->input)) != NULL) {
@@ -129,7 +131,7 @@ cmd_run_shell_free(void *data)
if (ctx->cmdclient != NULL) { if (ctx->cmdclient != NULL) {
ctx->cmdclient->references--; ctx->cmdclient->references--;
server_write_client(ctx->cmdclient, MSG_EXIT, NULL, 0); ctx->cmdclient->flags |= CLIENT_EXIT;
} }
if (ctx->curclient != NULL) if (ctx->curclient != NULL)
ctx->curclient->references--; ctx->curclient->references--;

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-save-buffer.c,v 1.10 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org> * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -25,64 +25,93 @@
#include "tmux.h" #include "tmux.h"
/* /*
* Saves a session paste buffer to a file. * Saves a paste buffer to a file.
*/ */
int cmd_save_buffer_exec(struct cmd *, struct cmd_ctx *); int cmd_save_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_save_buffer_entry = { const struct cmd_entry cmd_save_buffer_entry = {
"save-buffer", "saveb", "save-buffer", "saveb",
"[-a] " CMD_BUFFER_SESSION_USAGE " path", "ab:", 1, 1,
CMD_ARG1, "a", "[-a] " CMD_BUFFER_USAGE,
cmd_buffer_init, 0,
cmd_buffer_parse, NULL,
cmd_save_buffer_exec, NULL,
cmd_buffer_free, cmd_save_buffer_exec
cmd_buffer_print
}; };
int int
cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_buffer_data *data = self->data; struct args *args = self->args;
struct session *s; struct client *c = ctx->cmdclient;
struct session *s;
struct paste_buffer *pb; struct paste_buffer *pb;
mode_t mask; const char *path, *newpath, *wd;
char *cause;
int buffer;
mode_t mask;
FILE *f; FILE *f;
if ((s = cmd_find_session(ctx, data->target)) == NULL) if (!args_has(args, 'b')) {
return (-1); if ((pb = paste_get_top(&global_buffers)) == NULL) {
if (data->buffer == -1) {
if ((pb = paste_get_top(&s->buffers)) == NULL) {
ctx->error(ctx, "no buffers"); ctx->error(ctx, "no buffers");
return (-1); return (-1);
} }
} else { } else {
if ((pb = paste_get_index(&s->buffers, data->buffer)) == NULL) { buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
ctx->error(ctx, "no buffer %d", data->buffer); if (cause != NULL) {
ctx->error(ctx, "buffer %s", cause);
xfree(cause);
return (-1);
}
pb = paste_get_index(&global_buffers, buffer);
if (pb == NULL) {
ctx->error(ctx, "no buffer %d", buffer);
return (-1); return (-1);
} }
} }
mask = umask(S_IRWXG | S_IRWXO); path = args->argv[0];
if (cmd_check_flag(data->chflags, 'a')) if (strcmp(path, "-") == 0) {
f = fopen(data->arg, "ab"); if (c == NULL) {
else ctx->error(ctx, "%s: can't write to stdout", path);
f = fopen(data->arg, "wb"); return (-1);
umask(mask); }
if (f == NULL) { bufferevent_write(c->stdout_event, pb->data, pb->size);
ctx->error(ctx, "%s: %s", data->arg, strerror(errno)); } else {
return (-1); if (c != NULL)
} wd = c->cwd;
else if ((s = cmd_current_session(ctx, 0)) != NULL) {
wd = options_get_string(&s->options, "default-path");
if (*wd == '\0')
wd = s->cwd;
} else
wd = NULL;
if (wd != NULL && *wd != '\0') {
newpath = get_full_path(wd, path);
if (newpath != NULL)
path = newpath;
}
if (fwrite(pb->data, 1, pb->size, f) != pb->size) { mask = umask(S_IRWXG | S_IRWXO);
ctx->error(ctx, "%s: fwrite error", data->arg); if (args_has(self->args, 'a'))
fclose(f); f = fopen(path, "ab");
return (-1); else
f = fopen(path, "wb");
umask(mask);
if (f == NULL) {
ctx->error(ctx, "%s: %s", path, strerror(errno));
return (-1);
}
if (fwrite(pb->data, 1, pb->size, f) != pb->size) {
ctx->error(ctx, "%s: fwrite error", path);
fclose(f);
return (-1);
}
fclose(f);
} }
fclose(f);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-select-layout.c,v 1.10 2009-12-04 22:14:47 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,40 +24,60 @@
* Switch window to selected layout. * Switch window to selected layout.
*/ */
void cmd_select_layout_init(struct cmd *, int); void cmd_select_layout_key_binding(struct cmd *, int);
int cmd_select_layout_exec(struct cmd *, struct cmd_ctx *); int cmd_select_layout_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_select_layout_entry = { const struct cmd_entry cmd_select_layout_entry = {
"select-layout", "selectl", "select-layout", "selectl",
CMD_TARGET_WINDOW_USAGE " [layout-name]", "npt:", 0, 1,
CMD_ARG01, "", "[-np] " CMD_TARGET_WINDOW_USAGE " [layout-name]",
cmd_select_layout_init, 0,
cmd_target_parse, cmd_select_layout_key_binding,
cmd_select_layout_exec, NULL,
cmd_target_free, cmd_select_layout_exec
cmd_target_print };
const struct cmd_entry cmd_next_layout_entry = {
"next-layout", "nextl",
"t:", 0, 0,
CMD_TARGET_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_select_layout_exec
};
const struct cmd_entry cmd_previous_layout_entry = {
"previous-layout", "prevl",
"t:", 0, 0,
CMD_TARGET_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_select_layout_exec
}; };
void void
cmd_select_layout_init(struct cmd *self, int key) cmd_select_layout_key_binding(struct cmd *self, int key)
{ {
struct cmd_target_data *data;
cmd_target_init(self, key);
data = self->data;
switch (key) { switch (key) {
case ('1' | KEYC_ESCAPE): case '1' | KEYC_ESCAPE:
data->arg = xstrdup("even-horizontal"); self->args = args_create(1, "even-horizontal");
break; break;
case ('2' | KEYC_ESCAPE): case '2' | KEYC_ESCAPE:
data->arg = xstrdup("even-vertical"); self->args = args_create(1, "even-vertical");
break; break;
case ('3' | KEYC_ESCAPE): case '3' | KEYC_ESCAPE:
data->arg = xstrdup("main-horizontal"); self->args = args_create(1, "main-horizontal");
break; break;
case ('4' | KEYC_ESCAPE): case '4' | KEYC_ESCAPE:
data->arg = xstrdup("main-vertical"); self->args = args_create(1, "main-vertical");
break;
case '5' | KEYC_ESCAPE:
self->args = args_create(1, "tiled");
break;
default:
self->args = args_create(0);
break; break;
} }
} }
@@ -65,24 +85,49 @@ cmd_select_layout_init(struct cmd *self, int key)
int int
cmd_select_layout_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_select_layout_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct winlink *wl; struct winlink *wl;
int layout; const char *layoutname;
int next, previous, layout;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
return (-1); return (-1);
if (data->arg == NULL) { next = self->entry == &cmd_next_layout_entry;
layout = wl->window->lastlayout; if (args_has(self->args, 'n'))
if (layout == -1) next = 1;
return (0); previous = self->entry == &cmd_previous_layout_entry;
} else if ((layout = layout_set_lookup(data->arg)) == -1) { if (args_has(self->args, 'p'))
ctx->error(ctx, "unknown layout or ambiguous: %s", data->arg); previous = 1;
return (-1);
if (next || previous) {
if (next)
layout = layout_set_next(wl->window);
else
layout = layout_set_previous(wl->window);
ctx->info(ctx, "arranging in: %s", layout_set_name(layout));
return (0);
} }
layout = layout_set_select(wl->window, layout); if (args->argc == 0)
ctx->info(ctx, "arranging in: %s", layout_set_name(layout)); layout = wl->window->lastlayout;
else
layout = layout_set_lookup(args->argv[0]);
if (layout != -1) {
layout = layout_set_select(wl->window, layout);
ctx->info(ctx, "arranging in: %s", layout_set_name(layout));
return (0);
}
if (args->argc != 0) {
layoutname = args->argv[0];
if (layout_parse(wl->window, layoutname) == -1) {
ctx->error(ctx, "can't set layout: %s", layoutname);
return (-1);
}
ctx->info(ctx, "arranging in: %s", layoutname);
return (0);
}
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-select-pane.c,v 1.12 2010-01-05 23:52:37 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,33 +24,90 @@
* Select pane. * Select pane.
*/ */
void cmd_select_pane_key_binding(struct cmd *, int);
int cmd_select_pane_exec(struct cmd *, struct cmd_ctx *); int cmd_select_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_select_pane_entry = { const struct cmd_entry cmd_select_pane_entry = {
"select-pane", "selectp", "select-pane", "selectp",
CMD_TARGET_PANE_USAGE, "lDLRt:U", 0, 0,
0, "", "[-lDLRU] " CMD_TARGET_PANE_USAGE,
cmd_target_init, 0,
cmd_target_parse, cmd_select_pane_key_binding,
cmd_select_pane_exec, NULL,
cmd_target_free, cmd_select_pane_exec
cmd_target_print
}; };
const struct cmd_entry cmd_last_pane_entry = {
"last-pane", "lastp",
"t:", 0, 0,
CMD_TARGET_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_select_pane_exec
};
void
cmd_select_pane_key_binding(struct cmd *self, int key)
{
self->args = args_create(0);
if (key == KEYC_UP)
args_set(self->args, 'U', NULL);
if (key == KEYC_DOWN)
args_set(self->args, 'D', NULL);
if (key == KEYC_LEFT)
args_set(self->args, 'L', NULL);
if (key == KEYC_RIGHT)
args_set(self->args, 'R', NULL);
if (key == 'o')
args_set(self->args, 't', ":.+");
}
int int
cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct winlink *wl; struct winlink *wl;
struct window_pane *wp; struct window_pane *wp;
if ((wl = cmd_find_pane(ctx, data->target, NULL, &wp)) == NULL) if (self->entry == &cmd_last_pane_entry || args_has(args, 'l')) {
wl = cmd_find_window(ctx, args_get(args, 't'), NULL);
if (wl == NULL)
return (-1);
if (wl->window->last == NULL) {
ctx->error(ctx, "no last pane");
return (-1);
}
window_set_active_pane(wl->window, wl->window->last);
server_status_window(wl->window);
server_redraw_window_borders(wl->window);
return (0);
}
if ((wl = cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp)) == NULL)
return (-1); return (-1);
if (!window_pane_visible(wp)) { if (!window_pane_visible(wp)) {
ctx->error(ctx, "pane not visible: %s", data->target); ctx->error(ctx, "pane not visible");
return (-1); return (-1);
} }
if (args_has(self->args, 'L'))
wp = window_pane_find_left(wp);
else if (args_has(self->args, 'R'))
wp = window_pane_find_right(wp);
else if (args_has(self->args, 'U'))
wp = window_pane_find_up(wp);
else if (args_has(self->args, 'D'))
wp = window_pane_find_down(wp);
if (wp == NULL) {
ctx->error(ctx, "pane not found");
return (-1);
}
window_set_active_pane(wl->window, wp); window_set_active_pane(wl->window, wp);
server_status_window(wl->window); server_status_window(wl->window);
server_redraw_window_borders(wl->window); server_redraw_window_borders(wl->window);

View File

@@ -1,91 +0,0 @@
/* $Id: cmd-select-prompt.c,v 1.13 2009-11-14 17:56:39 tcunha Exp $ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 <stdlib.h>
#include "tmux.h"
/*
* Prompt for window index and select it.
*/
int cmd_select_prompt_exec(struct cmd *, struct cmd_ctx *);
int cmd_select_prompt_callback(void *, const char *);
const struct cmd_entry cmd_select_prompt_entry = {
"select-prompt", NULL,
CMD_TARGET_CLIENT_USAGE,
0, "",
cmd_target_init,
cmd_target_parse,
cmd_select_prompt_exec,
cmd_target_free,
cmd_target_print
};
int
cmd_select_prompt_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct client *c;
if ((c = cmd_find_client(ctx, data->target)) == NULL)
return (-1);
if (c->prompt_string != NULL)
return (0);
status_prompt_set(c, "index ", cmd_select_prompt_callback, NULL, c, 0);
return (0);
}
int
cmd_select_prompt_callback(void *data, const char *s)
{
struct client *c = data;
const char *errstr;
char msg[128];
u_int idx;
if (s == NULL || *s == '\0')
return (0);
idx = strtonum(s, 0, UINT_MAX, &errstr);
if (errstr != NULL) {
xsnprintf(msg, sizeof msg, "Index %s: %s", errstr, s);
status_message_set(c, "%s", msg);
return (0);
}
if (winlink_find_by_index(&c->session->windows, idx) == NULL) {
xsnprintf(msg, sizeof msg,
"Window not found: %s:%d", c->session->name, idx);
status_message_set(c, "%s", msg);
return (0);
}
if (session_select(c->session, idx) == 0)
server_redraw_session(c->session);
recalculate_sizes();
return (0);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-select-window.c,v 1.24 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -26,43 +26,113 @@
* Select window by index. * Select window by index.
*/ */
void cmd_select_window_init(struct cmd *, int); void cmd_select_window_key_binding(struct cmd *, int);
int cmd_select_window_exec(struct cmd *, struct cmd_ctx *); int cmd_select_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_select_window_entry = { const struct cmd_entry cmd_select_window_entry = {
"select-window", "selectw", "select-window", "selectw",
CMD_TARGET_WINDOW_USAGE, "lnpt:", 0, 0,
0, "", "[-lnp] " CMD_TARGET_WINDOW_USAGE,
cmd_select_window_init, 0,
cmd_target_parse, cmd_select_window_key_binding,
cmd_select_window_exec, NULL,
cmd_target_free, cmd_select_window_exec
cmd_target_print };
const struct cmd_entry cmd_next_window_entry = {
"next-window", "next",
"at:", 0, 0,
"[-a] " CMD_TARGET_SESSION_USAGE,
0,
cmd_select_window_key_binding,
NULL,
cmd_select_window_exec
};
const struct cmd_entry cmd_previous_window_entry = {
"previous-window", "prev",
"at:", 0, 0,
"[-a] " CMD_TARGET_SESSION_USAGE,
0,
cmd_select_window_key_binding,
NULL,
cmd_select_window_exec
};
const struct cmd_entry cmd_last_window_entry = {
"last-window", "last",
"t:", 0, 0,
CMD_TARGET_SESSION_USAGE,
0,
NULL,
NULL,
cmd_select_window_exec
}; };
void void
cmd_select_window_init(struct cmd *self, int key) cmd_select_window_key_binding(struct cmd *self, int key)
{ {
struct cmd_target_data *data; char tmp[16];
cmd_target_init(self, key); self->args = args_create(0);
data = self->data; if (key >= '0' && key <= '9') {
xsnprintf(tmp, sizeof tmp, ":%d", key - '0');
xasprintf(&data->target, ":%d", key - '0'); args_set(self->args, 't', tmp);
}
if (key == ('n' | KEYC_ESCAPE) || key == ('p' | KEYC_ESCAPE))
args_set(self->args, 'a', NULL);
} }
int int
cmd_select_window_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_select_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct winlink *wl; struct winlink *wl;
struct session *s; struct session *s;
int next, previous, last, activity;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) next = self->entry == &cmd_next_window_entry;
return (-1); if (args_has(self->args, 'n'))
next = 1;
previous = self->entry == &cmd_previous_window_entry;
if (args_has(self->args, 'p'))
previous = 1;
last = self->entry == &cmd_last_window_entry;
if (args_has(self->args, 'l'))
last = 1;
if (next || previous || last) {
s = cmd_find_session(ctx, args_get(args, 't'), 0);
if (s == NULL)
return (-1);
activity = args_has(self->args, 'a');
if (next) {
if (session_next(s, activity) != 0) {
ctx->error(ctx, "no next window");
return (-1);
}
} else if (previous) {
if (session_previous(s, activity) != 0) {
ctx->error(ctx, "no previous window");
return (-1);
}
} else {
if (session_last(s) != 0) {
ctx->error(ctx, "no last window");
return (-1);
}
}
if (session_select(s, wl->idx) == 0)
server_redraw_session(s); server_redraw_session(s);
} else {
wl = cmd_find_window(ctx, args_get(args, 't'), &s);
if (wl == NULL)
return (-1);
if (session_select(s, wl->idx) == 0)
server_redraw_session(s);
}
recalculate_sizes(); recalculate_sizes();
return (0); return (0);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-send-keys.c,v 1.24 2009-12-04 22:14:47 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -19,6 +19,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include "tmux.h" #include "tmux.h"
@@ -26,127 +27,57 @@
* Send keys to client. * Send keys to client.
*/ */
int cmd_send_keys_parse(struct cmd *, int, char **, char **);
int cmd_send_keys_exec(struct cmd *, struct cmd_ctx *); int cmd_send_keys_exec(struct cmd *, struct cmd_ctx *);
void cmd_send_keys_free(struct cmd *);
size_t cmd_send_keys_print(struct cmd *, char *, size_t);
struct cmd_send_keys_data {
char *target;
u_int nkeys;
int *keys;
};
const struct cmd_entry cmd_send_keys_entry = { const struct cmd_entry cmd_send_keys_entry = {
"send-keys", "send", "send-keys", "send",
"[-t target-pane] key ...", "Rt:", 0, -1,
0, "", "[-R] [-t target-pane] key ...",
0,
NULL, NULL,
cmd_send_keys_parse, NULL,
cmd_send_keys_exec, cmd_send_keys_exec
cmd_send_keys_free,
cmd_send_keys_print
}; };
int
cmd_send_keys_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_send_keys_data *data;
int opt, key;
char *s;
self->data = data = xmalloc(sizeof *data);
data->target = NULL;
data->nkeys = 0;
data->keys = NULL;
while ((opt = getopt(argc, argv, "t:")) != -1) {
switch (opt) {
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc == 0)
goto usage;
while (argc-- != 0) {
if ((key = key_string_lookup_string(*argv)) != KEYC_NONE) {
data->keys = xrealloc(
data->keys, data->nkeys + 1, sizeof *data->keys);
data->keys[data->nkeys++] = key;
} else {
for (s = *argv; *s != '\0'; s++) {
data->keys = xrealloc(data->keys,
data->nkeys + 1, sizeof *data->keys);
data->keys[data->nkeys++] = *s;
}
}
argv++;
}
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
self->entry->free(self);
return (-1);
}
int int
cmd_send_keys_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_send_keys_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_send_keys_data *data = self->data; struct args *args = self->args;
struct window_pane *wp; struct window_pane *wp;
u_int i; struct session *s;
struct input_ctx *ictx;
const char *str;
int i, key;
if (data == NULL) if (cmd_find_pane(ctx, args_get(args, 't'), &s, &wp) == NULL)
return (-1); return (-1);
if (cmd_find_pane(ctx, data->target, NULL, &wp) == NULL) if (args_has(args, 'R')) {
return (-1); ictx = &wp->ictx;
for (i = 0; i < data->nkeys; i++) memcpy(&ictx->cell, &grid_default_cell, sizeof ictx->cell);
window_pane_key(wp, ctx->curclient, data->keys[i]); memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
ictx->old_cx = 0;
ictx->old_cy = 0;
if (wp->mode == NULL)
screen_write_start(&ictx->ctx, wp, &wp->base);
else
screen_write_start(&ictx->ctx, NULL, &wp->base);
screen_write_reset(&ictx->ctx);
screen_write_stop(&ictx->ctx);
}
for (i = 0; i < args->argc; i++) {
str = args->argv[i];
if ((key = key_string_lookup_string(str)) != KEYC_NONE) {
window_pane_key(wp, s, key);
} else {
for (; *str != '\0'; str++)
window_pane_key(wp, s, *str);
}
}
return (0); return (0);
} }
void
cmd_send_keys_free(struct cmd *self)
{
struct cmd_send_keys_data *data = self->data;
if (data->target != NULL)
xfree(data->target);
xfree(data);
}
size_t
cmd_send_keys_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_send_keys_data *data = self->data;
size_t off = 0;
u_int i;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
for (i = 0; i < data->nkeys; i++) {
if (off >= len)
break;
off += xsnprintf(buf + off,
len - off, " %s", key_string_lookup_key(data->keys[i]));
}
return (off);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-send-prefix.c,v 1.28 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,28 +28,30 @@ int cmd_send_prefix_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_send_prefix_entry = { const struct cmd_entry cmd_send_prefix_entry = {
"send-prefix", NULL, "send-prefix", NULL,
CMD_TARGET_PANE_USAGE, "2t:", 0, 0,
0, "", "[-2] " CMD_TARGET_PANE_USAGE,
cmd_target_init, 0,
cmd_target_parse, NULL,
cmd_send_prefix_exec, NULL,
cmd_target_free, cmd_send_prefix_exec
cmd_target_print
}; };
int int
cmd_send_prefix_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_send_prefix_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct session *s; struct session *s;
struct window_pane *wp; struct window_pane *wp;
struct keylist *keylist; int key;
if (cmd_find_pane(ctx, data->target, &s, &wp) == NULL) if (cmd_find_pane(ctx, args_get(args, 't'), &s, &wp) == NULL)
return (-1); return (-1);
keylist = options_get_data(&s->options, "prefix"); if (args_has(args, '2'))
window_pane_key(wp, ctx->curclient, ARRAY_FIRST(keylist)); key = options_get_number(&s->options, "prefix2");
else
key = options_get_number(&s->options, "prefix");
window_pane_key(wp, s, key);
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-server-info.c,v 1.37 2009-12-10 16:59:02 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -34,45 +34,44 @@ int cmd_server_info_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_server_info_entry = { const struct cmd_entry cmd_server_info_entry = {
"server-info", "info", "server-info", "info",
"", 0, 0,
"", "",
0, "", 0,
NULL, NULL,
NULL, NULL,
cmd_server_info_exec, cmd_server_info_exec
NULL,
NULL
}; };
/* ARGSUSED */ /* ARGSUSED */
int int
cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx) cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
{ {
struct tty_term *term; struct tty_term *term;
struct client *c; struct client *c;
struct session *s; struct session *s;
struct winlink *wl; struct winlink *wl;
struct window *w; struct window *w;
struct window_pane *wp; struct window_pane *wp;
struct tty_code *code; struct tty_code *code;
struct tty_term_code_entry *ent; const struct tty_term_code_entry *ent;
struct utsname un; struct utsname un;
struct job *job; struct job *job;
struct grid *gd; struct grid *gd;
struct grid_line *gl; struct grid_line *gl;
u_int i, j, k; u_int i, j, k;
char out[80]; char out[80];
char *tim; char *tim;
time_t t; time_t t;
u_int lines, ulines; u_int lines, ulines;
size_t size, usize; size_t size, usize;
tim = ctime(&start_time); tim = ctime(&start_time);
*strchr(tim, '\n') = '\0'; *strchr(tim, '\n') = '\0';
ctx->print(ctx, ctx->print(ctx,
"tmux " BUILD ", pid %ld, started %s", (long) getpid(), tim); "tmux " VERSION ", pid %ld, started %s", (long) getpid(), tim);
ctx->print( ctx->print(
ctx, "socket path %s, debug level %d", socket_path, debug_level); ctx, "socket path %s, debug level %d", socket_path, debug_level);
if (uname(&un) == 0) { if (uname(&un) >= 0) {
ctx->print(ctx, "system is %s %s %s %s", ctx->print(ctx, "system is %s %s %s %s",
un.sysname, un.release, un.version, un.machine); un.sysname, un.release, un.version, un.machine);
} }
@@ -81,8 +80,6 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
else else
ctx->print(ctx, "configuration file not specified"); ctx->print(ctx, "configuration file not specified");
ctx->print(ctx, "protocol version is %d", PROTOCOL_VERSION); ctx->print(ctx, "protocol version is %d", PROTOCOL_VERSION);
ctx->print(ctx, "%u clients, %u sessions",
ARRAY_LENGTH(&clients), ARRAY_LENGTH(&sessions));
ctx->print(ctx, "%s", ""); ctx->print(ctx, "%s", "");
ctx->print(ctx, "Clients:"); ctx->print(ctx, "Clients:");
@@ -91,29 +88,25 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
if (c == NULL || c->session == NULL) if (c == NULL || c->session == NULL)
continue; continue;
ctx->print(ctx, "%2d: %s (%d, %d): %s [%ux%u %s] " ctx->print(ctx,"%2d: %s (%d, %d): %s [%ux%u %s bs=%hho] "
"[flags=0x%x/0x%x, references=%u]", i, c->tty.path, "[flags=0x%x/0x%x, references=%u]", i, c->tty.path,
c->ibuf.fd, c->tty.fd, c->session->name, c->ibuf.fd, c->tty.fd, c->session->name,
c->tty.sx, c->tty.sy, c->tty.termname, c->flags, c->tty.sx, c->tty.sy, c->tty.termname,
c->tty.tio.c_cc[VERASE], c->flags,
c->tty.flags, c->references); c->tty.flags, c->references);
} }
ctx->print(ctx, "%s", ""); ctx->print(ctx, "%s", "");
ctx->print(ctx, "Sessions: [%zu/%zu]", ctx->print(ctx, "Sessions: [%zu/%zu]",
sizeof (struct grid_cell), sizeof (struct grid_utf8)); sizeof (struct grid_cell), sizeof (struct grid_utf8));
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { RB_FOREACH(s, sessions, &sessions) {
s = ARRAY_ITEM(&sessions, i);
if (s == NULL)
continue;
t = s->creation_time.tv_sec; t = s->creation_time.tv_sec;
tim = ctime(&t); tim = ctime(&t);
*strchr(tim, '\n') = '\0'; *strchr(tim, '\n') = '\0';
ctx->print(ctx, "%2u: %s: %u windows (created %s) [%ux%u] " ctx->print(ctx, "%2u: %s: %u windows (created %s) [%ux%u] "
"[flags=0x%x, references=%u]", i, s->name, "[flags=0x%x]", s->idx, s->name,
winlink_count(&s->windows), tim, s->sx, s->sy, s->flags, winlink_count(&s->windows), tim, s->sx, s->sy, s->flags);
s->references);
RB_FOREACH(wl, winlinks, &s->windows) { RB_FOREACH(wl, winlinks, &s->windows) {
w = wl->window; w = wl->window;
ctx->print(ctx, "%4u: %s [%ux%u] [flags=0x%x, " ctx->print(ctx, "%4u: %s [%ux%u] [flags=0x%x, "
@@ -149,7 +142,7 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
ctx->print(ctx, "%s", ""); ctx->print(ctx, "%s", "");
ctx->print(ctx, "Terminals:"); ctx->print(ctx, "Terminals:");
SLIST_FOREACH(term, &tty_terms, entry) { LIST_FOREACH(term, &tty_terms, entry) {
ctx->print(ctx, "%s [references=%u, flags=0x%x]:", ctx->print(ctx, "%s [references=%u, flags=0x%x]:",
term->name, term->references, term->flags); term->name, term->references, term->flags);
for (i = 0; i < NTTYCODE; i++) { for (i = 0; i < NTTYCODE; i++) {
@@ -181,9 +174,9 @@ cmd_server_info_exec(unused struct cmd *self, struct cmd_ctx *ctx)
ctx->print(ctx, "%s", ""); ctx->print(ctx, "%s", "");
ctx->print(ctx, "Jobs:"); ctx->print(ctx, "Jobs:");
SLIST_FOREACH(job, &all_jobs, lentry) { LIST_FOREACH(job, &all_jobs, lentry) {
ctx->print(ctx, "%s [fd=%d, pid=%d, status=%d, flags=0x%x]", ctx->print(ctx, "%s [fd=%d, pid=%d, status=%d]",
job->cmd, job->fd, job->pid, job->status, job->flags); job->cmd, job->fd, job->pid, job->status);
} }
return (0); return (0);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-set-buffer.c,v 1.12 2009-11-28 14:54:12 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -23,46 +23,53 @@
#include "tmux.h" #include "tmux.h"
/* /*
* Add or set a session paste buffer. * Add or set a paste buffer.
*/ */
int cmd_set_buffer_exec(struct cmd *, struct cmd_ctx *); int cmd_set_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_set_buffer_entry = { const struct cmd_entry cmd_set_buffer_entry = {
"set-buffer", "setb", "set-buffer", "setb",
CMD_BUFFER_SESSION_USAGE " data", "b:", 1, 1,
CMD_ARG1, "", CMD_BUFFER_USAGE " data",
cmd_buffer_init, 0,
cmd_buffer_parse, NULL,
cmd_set_buffer_exec, NULL,
cmd_buffer_free, cmd_set_buffer_exec
cmd_buffer_print
}; };
int int
cmd_set_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_set_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_buffer_data *data = self->data; struct args *args = self->args;
struct session *s; u_int limit;
u_int limit; char *pdata, *cause;
char *pdata; size_t psize;
size_t psize; int buffer;
if ((s = cmd_find_session(ctx, data->target)) == NULL) limit = options_get_number(&global_options, "buffer-limit");
return (-1);
limit = options_get_number(&s->options, "buffer-limit");
pdata = xstrdup(data->arg); pdata = xstrdup(args->argv[0]);
psize = strlen(pdata); psize = strlen(pdata);
if (data->buffer == -1) { if (!args_has(args, 'b')) {
paste_add(&s->buffers, pdata, psize, limit); paste_add(&global_buffers, pdata, psize, limit);
return (0); return (0);
} }
if (paste_replace(&s->buffers, data->buffer, pdata, psize) != 0) {
ctx->error(ctx, "no buffer %d", data->buffer); buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
if (cause != NULL) {
ctx->error(ctx, "buffer %s", cause);
xfree(cause);
xfree(pdata); xfree(pdata);
return (-1); return (-1);
} }
if (paste_replace(&global_buffers, buffer, pdata, psize) != 0) {
ctx->error(ctx, "no buffer %d", buffer);
xfree(pdata);
return (-1);
}
return (0); return (0);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-set-environment.c,v 1.3 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,57 +31,63 @@ int cmd_set_environment_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_set_environment_entry = { const struct cmd_entry cmd_set_environment_entry = {
"set-environment", "setenv", "set-environment", "setenv",
"grt:u", 1, 2,
"[-gru] " CMD_TARGET_SESSION_USAGE " name [value]", "[-gru] " CMD_TARGET_SESSION_USAGE " name [value]",
CMD_ARG12, "gru", 0,
NULL, NULL,
cmd_target_parse, NULL,
cmd_set_environment_exec, cmd_set_environment_exec
cmd_target_free,
cmd_target_print
}; };
int int
cmd_set_environment_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_set_environment_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct session *s; struct session *s;
struct environ *env; struct environ *env;
const char *name, *value;
if (*data->arg == '\0') { name = args->argv[0];
if (*name == '\0') {
ctx->error(ctx, "empty variable name"); ctx->error(ctx, "empty variable name");
return (-1); return (-1);
} }
if (strchr(data->arg, '=') != NULL) { if (strchr(name, '=') != NULL) {
ctx->error(ctx, "variable name contains ="); ctx->error(ctx, "variable name contains =");
return (-1); return (-1);
} }
if (cmd_check_flag(data->chflags, 'g')) if (args->argc < 1)
value = NULL;
else
value = args->argv[1];
if (args_has(self->args, 'g'))
env = &global_environ; env = &global_environ;
else { else {
if ((s = cmd_find_session(ctx, data->target)) == NULL) if ((s = cmd_find_session(ctx, args_get(args, 't'), 0)) == NULL)
return (-1); return (-1);
env = &s->environ; env = &s->environ;
} }
if (cmd_check_flag(data->chflags, 'u')) { if (args_has(self->args, 'u')) {
if (data->arg2 != NULL) { if (value != NULL) {
ctx->error(ctx, "can't specify a value with -u"); ctx->error(ctx, "can't specify a value with -u");
return (-1); return (-1);
} }
environ_unset(env, data->arg); environ_unset(env, name);
} else if (cmd_check_flag(data->chflags, 'r')) { } else if (args_has(self->args, 'r')) {
if (data->arg2 != NULL) { if (value != NULL) {
ctx->error(ctx, "can't specify a value with -r"); ctx->error(ctx, "can't specify a value with -r");
return (-1); return (-1);
} }
environ_set(env, data->arg, NULL); environ_set(env, name, NULL);
} else { } else {
if (data->arg2 == NULL) { if (value == NULL) {
ctx->error(ctx, "no value specified"); ctx->error(ctx, "no value specified");
return (-1); return (-1);
} }
environ_set(env, data->arg, data->arg2); environ_set(env, name, value);
} }
return (0); return (0);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-set-option.c,v 1.96 2010-02-26 13:31:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,252 +29,161 @@
int cmd_set_option_exec(struct cmd *, struct cmd_ctx *); int cmd_set_option_exec(struct cmd *, struct cmd_ctx *);
const char *cmd_set_option_print( int cmd_set_option_find(const char *, const struct options_table_entry **,
const struct set_option_entry *, struct options_entry *); const struct options_table_entry **);
void cmd_set_option_string(struct cmd_ctx *,
struct options *, const struct set_option_entry *, char *, int); int cmd_set_option_unset(struct cmd *, struct cmd_ctx *,
void cmd_set_option_number(struct cmd_ctx *, const struct options_table_entry *, struct options *,
struct options *, const struct set_option_entry *, char *); const char *);
void cmd_set_option_keys(struct cmd_ctx *, int cmd_set_option_set(struct cmd *, struct cmd_ctx *,
struct options *, const struct set_option_entry *, char *); const struct options_table_entry *, struct options *,
void cmd_set_option_colour(struct cmd_ctx *, const char *);
struct options *, const struct set_option_entry *, char *);
void cmd_set_option_attributes(struct cmd_ctx *, struct options_entry *cmd_set_option_string(struct cmd *, struct cmd_ctx *,
struct options *, const struct set_option_entry *, char *); const struct options_table_entry *, struct options *,
void cmd_set_option_flag(struct cmd_ctx *, const char *);
struct options *, const struct set_option_entry *, char *); struct options_entry *cmd_set_option_number(struct cmd *, struct cmd_ctx *,
void cmd_set_option_choice(struct cmd_ctx *, const struct options_table_entry *, struct options *,
struct options *, const struct set_option_entry *, char *); const char *);
struct options_entry *cmd_set_option_key(struct cmd *, struct cmd_ctx *,
const struct options_table_entry *, struct options *,
const char *);
struct options_entry *cmd_set_option_colour(struct cmd *, struct cmd_ctx *,
const struct options_table_entry *, struct options *,
const char *);
struct options_entry *cmd_set_option_attributes(struct cmd *, struct cmd_ctx *,
const struct options_table_entry *, struct options *,
const char *);
struct options_entry *cmd_set_option_flag(struct cmd *, struct cmd_ctx *,
const struct options_table_entry *, struct options *,
const char *);
struct options_entry *cmd_set_option_choice(struct cmd *, struct cmd_ctx *,
const struct options_table_entry *, struct options *,
const char *);
const struct cmd_entry cmd_set_option_entry = { const struct cmd_entry cmd_set_option_entry = {
"set-option", "set", "set-option", "set",
"agst:uw", 1, 2,
"[-agsuw] [-t target-session|target-window] option [value]", "[-agsuw] [-t target-session|target-window] option [value]",
CMD_ARG12, "agsuw", 0,
NULL, NULL,
cmd_target_parse, NULL,
cmd_set_option_exec, cmd_set_option_exec
cmd_target_free,
cmd_target_print
}; };
const char *set_option_mode_keys_list[] = { const struct cmd_entry cmd_set_window_option_entry = {
"emacs", "vi", NULL "set-window-option", "setw",
}; "agt:u", 1, 2,
const char *set_option_clock_mode_style_list[] = { "[-agu] " CMD_TARGET_WINDOW_USAGE " option [value]",
"12", "24", NULL 0,
}; NULL,
const char *set_option_status_keys_list[] = { NULL,
"emacs", "vi", NULL cmd_set_option_exec
};
const char *set_option_status_justify_list[] = {
"left", "centre", "right", NULL
};
const char *set_option_bell_action_list[] = {
"none", "any", "current", NULL
}; };
const struct set_option_entry set_option_table[] = { /* Look for an option in all three tables. */
{ "escape-time", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, int
{ "quiet", SET_OPTION_FLAG, 0, 0, NULL }, cmd_set_option_find(
{ NULL, 0, 0, 0, NULL } const char *optstr, const struct options_table_entry **table,
}; const struct options_table_entry **oe)
{
static const struct options_table_entry *tables[] = {
server_options_table,
window_options_table,
session_options_table
};
const struct options_table_entry *oe_loop;
u_int i;
const struct set_option_entry set_session_option_table[] = { for (i = 0; i < nitems(tables); i++) {
{ "base-index", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, for (oe_loop = tables[i]; oe_loop->name != NULL; oe_loop++) {
{ "bell-action", SET_OPTION_CHOICE, 0, 0, set_option_bell_action_list }, if (strncmp(oe_loop->name, optstr, strlen(optstr)) != 0)
{ "buffer-limit", SET_OPTION_NUMBER, 1, INT_MAX, NULL }, continue;
{ "default-command", SET_OPTION_STRING, 0, 0, NULL },
{ "default-path", SET_OPTION_STRING, 0, 0, NULL },
{ "default-shell", SET_OPTION_STRING, 0, 0, NULL },
{ "default-terminal", SET_OPTION_STRING, 0, 0, NULL },
{ "display-panes-colour", SET_OPTION_COLOUR, 0, 0, NULL },
{ "display-panes-active-colour", SET_OPTION_COLOUR, 0, 0, NULL },
{ "display-panes-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
{ "display-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
{ "history-limit", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
{ "lock-after-time", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
{ "lock-command", SET_OPTION_STRING, 0, 0, NULL },
{ "lock-server", SET_OPTION_FLAG, 0, 0, NULL },
{ "message-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
{ "message-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "message-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "message-limit", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
{ "mouse-select-pane", SET_OPTION_FLAG, 0, 0, NULL },
{ "pane-active-border-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "pane-active-border-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "pane-border-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "pane-border-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "prefix", SET_OPTION_KEYS, 0, 0, NULL },
{ "repeat-time", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
{ "set-remain-on-exit", SET_OPTION_FLAG, 0, 0, NULL },
{ "set-titles", SET_OPTION_FLAG, 0, 0, NULL },
{ "set-titles-string", SET_OPTION_STRING, 0, 0, NULL },
{ "status", SET_OPTION_FLAG, 0, 0, NULL },
{ "status-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
{ "status-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "status-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "status-interval", SET_OPTION_NUMBER, 0, INT_MAX, NULL },
{ "status-justify",
SET_OPTION_CHOICE, 0, 0, set_option_status_justify_list },
{ "status-keys", SET_OPTION_CHOICE, 0, 0, set_option_status_keys_list },
{ "status-left", SET_OPTION_STRING, 0, 0, NULL },
{ "status-left-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
{ "status-left-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "status-left-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "status-left-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
{ "status-right", SET_OPTION_STRING, 0, 0, NULL },
{ "status-right-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
{ "status-right-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "status-right-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "status-right-length", SET_OPTION_NUMBER, 0, SHRT_MAX, NULL },
{ "status-utf8", SET_OPTION_FLAG, 0, 0, NULL },
{ "terminal-overrides", SET_OPTION_STRING, 0, 0, NULL },
{ "update-environment", SET_OPTION_STRING, 0, 0, NULL },
{ "visual-activity", SET_OPTION_FLAG, 0, 0, NULL },
{ "visual-bell", SET_OPTION_FLAG, 0, 0, NULL },
{ "visual-content", SET_OPTION_FLAG, 0, 0, NULL },
{ NULL, 0, 0, 0, NULL }
};
const struct set_option_entry set_window_option_table[] = { /* If already found, ambiguous. */
{ "aggressive-resize", SET_OPTION_FLAG, 0, 0, NULL }, if (*oe != NULL)
{ "alternate-screen", SET_OPTION_FLAG, 0, 0, NULL }, return (-1);
{ "automatic-rename", SET_OPTION_FLAG, 0, 0, NULL }, *oe = oe_loop;
{ "clock-mode-colour", SET_OPTION_COLOUR, 0, 0, NULL }, *table = tables[i];
{ "clock-mode-style",
SET_OPTION_CHOICE, 0, 0, set_option_clock_mode_style_list }, /* Bail now if an exact match. */
{ "force-height", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, if (strcmp((*oe)->name, optstr) == 0)
{ "force-width", SET_OPTION_NUMBER, 0, INT_MAX, NULL }, break;
{ "main-pane-height", SET_OPTION_NUMBER, 1, INT_MAX, NULL }, }
{ "main-pane-width", SET_OPTION_NUMBER, 1, INT_MAX, NULL }, }
{ "mode-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL }, return (0);
{ "mode-bg", SET_OPTION_COLOUR, 0, 0, NULL }, }
{ "mode-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "mode-keys", SET_OPTION_CHOICE, 0, 0, set_option_mode_keys_list },
{ "mode-mouse", SET_OPTION_FLAG, 0, 0, NULL },
{ "monitor-activity", SET_OPTION_FLAG, 0, 0, NULL },
{ "monitor-content", SET_OPTION_STRING, 0, 0, NULL },
{ "remain-on-exit", SET_OPTION_FLAG, 0, 0, NULL },
{ "synchronize-panes", SET_OPTION_FLAG, 0, 0, NULL },
{ "utf8", SET_OPTION_FLAG, 0, 0, NULL },
{ "window-status-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
{ "window-status-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "window-status-current-attr", SET_OPTION_ATTRIBUTES, 0, 0, NULL },
{ "window-status-current-bg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "window-status-current-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "window-status-current-format", SET_OPTION_STRING, 0, 0, NULL },
{ "window-status-fg", SET_OPTION_COLOUR, 0, 0, NULL },
{ "window-status-format", SET_OPTION_STRING, 0, 0, NULL },
{ "word-separators", SET_OPTION_STRING, 0, 0, NULL },
{ "xterm-keys", SET_OPTION_FLAG, 0, 0, NULL },
{ NULL, 0, 0, 0, NULL }
};
int int
cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
const struct set_option_entry *table; const struct options_table_entry *table, *oe;
struct session *s; struct session *s;
struct winlink *wl; struct winlink *wl;
struct client *c; struct client *c;
struct options *oo; struct options *oo;
const struct set_option_entry *entry, *opt; const char *optstr, *valstr;
struct jobs *jobs; u_int i;
struct job *job, *nextjob;
u_int i;
int try_again;
if (cmd_check_flag(data->chflags, 's')) { /* Get the option name and value. */
optstr = args->argv[0];
if (*optstr == '\0') {
ctx->error(ctx, "invalid option");
return (-1);
}
if (args->argc < 2)
valstr = NULL;
else
valstr = args->argv[1];
/* Find the option entry, try each table. */
table = oe = NULL;
if (cmd_set_option_find(optstr, &table, &oe) != 0) {
ctx->error(ctx, "ambiguous option: %s", optstr);
return (-1);
}
if (oe == NULL) {
ctx->error(ctx, "unknown option: %s", optstr);
return (-1);
}
/* Work out the tree from the table. */
if (table == server_options_table)
oo = &global_options; oo = &global_options;
table = set_option_table; else if (table == window_options_table) {
} else if (cmd_check_flag(data->chflags, 'w')) { if (args_has(self->args, 'g'))
table = set_window_option_table;
if (cmd_check_flag(data->chflags, 'g'))
oo = &global_w_options; oo = &global_w_options;
else { else {
wl = cmd_find_window(ctx, data->target, NULL); wl = cmd_find_window(ctx, args_get(args, 't'), NULL);
if (wl == NULL) if (wl == NULL)
return (-1); return (-1);
oo = &wl->window->options; oo = &wl->window->options;
} }
} else { } else if (table == session_options_table) {
table = set_session_option_table; if (args_has(self->args, 'g'))
if (cmd_check_flag(data->chflags, 'g'))
oo = &global_s_options; oo = &global_s_options;
else { else {
s = cmd_find_session(ctx, data->target); s = cmd_find_session(ctx, args_get(args, 't'), 0);
if (s == NULL) if (s == NULL)
return (-1); return (-1);
oo = &s->options; oo = &s->options;
} }
}
if (*data->arg == '\0') {
ctx->error(ctx, "invalid option");
return (-1);
}
entry = NULL;
for (opt = table; opt->name != NULL; opt++) {
if (strncmp(opt->name, data->arg, strlen(data->arg)) != 0)
continue;
if (entry != NULL) {
ctx->error(ctx, "ambiguous option: %s", data->arg);
return (-1);
}
entry = opt;
/* Bail now if an exact match. */
if (strcmp(entry->name, data->arg) == 0)
break;
}
if (entry == NULL) {
ctx->error(ctx, "unknown option: %s", data->arg);
return (-1);
}
if (cmd_check_flag(data->chflags, 'u')) {
if (cmd_check_flag(data->chflags, 'g')) {
ctx->error(ctx,
"can't unset global option: %s", entry->name);
return (-1);
}
if (data->arg2 != NULL) {
ctx->error(ctx,
"value passed to unset option: %s", entry->name);
return (-1);
}
options_remove(oo, entry->name);
ctx->info(ctx, "unset option: %s", entry->name);
} else { } else {
switch (entry->type) { ctx->error(ctx, "unknown table");
case SET_OPTION_STRING: return (-1);
cmd_set_option_string(ctx, oo, entry,
data->arg2, cmd_check_flag(data->chflags, 'a'));
break;
case SET_OPTION_NUMBER:
cmd_set_option_number(ctx, oo, entry, data->arg2);
break;
case SET_OPTION_KEYS:
cmd_set_option_keys(ctx, oo, entry, data->arg2);
break;
case SET_OPTION_COLOUR:
cmd_set_option_colour(ctx, oo, entry, data->arg2);
break;
case SET_OPTION_ATTRIBUTES:
cmd_set_option_attributes(ctx, oo, entry, data->arg2);
break;
case SET_OPTION_FLAG:
cmd_set_option_flag(ctx, oo, entry, data->arg2);
break;
case SET_OPTION_CHOICE:
cmd_set_option_choice(ctx, oo, entry, data->arg2);
break;
}
} }
/* Unset or set the option. */
if (args_has(args, 'u')) {
if (cmd_set_option_unset(self, ctx, oe, oo, valstr) != 0)
return (-1);
} else {
if (cmd_set_option_set(self, ctx, oe, oo, valstr) != 0)
return (-1);
}
/* Update sizes and redraw. May not need it but meh. */
recalculate_sizes(); recalculate_sizes();
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i); c = ARRAY_ITEM(&clients, i);
@@ -282,226 +191,167 @@ cmd_set_option_exec(struct cmd *self, struct cmd_ctx *ctx)
server_redraw_client(c); server_redraw_client(c);
} }
/*
* Special-case: kill all persistent jobs if status-left, status-right
* or set-titles-string have changed. Persistent jobs are only used by
* the status line at the moment so this works XXX.
*/
if (strcmp(entry->name, "status-left") == 0 ||
strcmp(entry->name, "status-right") == 0 ||
strcmp(entry->name, "set-titles-string") == 0 ||
strcmp(entry->name, "window-status-format") == 0) {
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session == NULL)
continue;
jobs = &c->status_jobs;
do {
try_again = 0;
job = RB_ROOT(jobs);
while (job != NULL) {
nextjob = RB_NEXT(jobs, jobs, job);
if (job->flags & JOB_PERSIST) {
job_remove(jobs, job);
try_again = 1;
break;
}
job = nextjob;
}
} while (try_again);
server_redraw_client(c);
}
}
return (0); return (0);
} }
const char * /* Unset an option. */
cmd_set_option_print( int
const struct set_option_entry *entry, struct options_entry *o) cmd_set_option_unset(struct cmd *self, struct cmd_ctx *ctx,
const struct options_table_entry *oe, struct options *oo, const char *value)
{ {
static char out[BUFSIZ]; struct args *args = self->args;
const char *s;
struct keylist *keylist;
u_int i;
*out = '\0'; if (args_has(args, 'g')) {
switch (entry->type) { ctx->error(ctx, "can't unset global option: %s", oe->name);
case SET_OPTION_STRING: return (-1);
xsnprintf(out, sizeof out, "\"%s\"", o->str);
break;
case SET_OPTION_NUMBER:
xsnprintf(out, sizeof out, "%lld", o->num);
break;
case SET_OPTION_KEYS:
keylist = o->data;
for (i = 0; i < ARRAY_LENGTH(keylist); i++) {
strlcat(out, key_string_lookup_key(
ARRAY_ITEM(keylist, i)), sizeof out);
if (i != ARRAY_LENGTH(keylist) - 1)
strlcat(out, ",", sizeof out);
}
break;
case SET_OPTION_COLOUR:
s = colour_tostring(o->num);
xsnprintf(out, sizeof out, "%s", s);
break;
case SET_OPTION_ATTRIBUTES:
s = attributes_tostring(o->num);
xsnprintf(out, sizeof out, "%s", s);
break;
case SET_OPTION_FLAG:
if (o->num)
strlcpy(out, "on", sizeof out);
else
strlcpy(out, "off", sizeof out);
break;
case SET_OPTION_CHOICE:
s = entry->choices[o->num];
xsnprintf(out, sizeof out, "%s", s);
break;
} }
return (out); if (value != NULL) {
ctx->error(ctx, "value passed to unset option: %s", oe->name);
return (-1);
}
options_remove(oo, oe->name);
ctx->info(ctx, "unset option: %s", oe->name);
return (0);
} }
void /* Set an option. */
cmd_set_option_string(struct cmd_ctx *ctx, struct options *oo, int
const struct set_option_entry *entry, char *value, int append) cmd_set_option_set(struct cmd *self, struct cmd_ctx *ctx,
const struct options_table_entry *oe, struct options *oo, const char *value)
{ {
struct options_entry *o; struct options_entry *o;
char *oldvalue, *newvalue; const char *s;
if (value == NULL) { if (oe->type != OPTIONS_TABLE_FLAG && value == NULL) {
ctx->error(ctx, "empty value"); ctx->error(ctx, "empty value");
return; return (-1);
} }
if (append) { o = NULL;
oldvalue = options_get_string(oo, entry->name); switch (oe->type) {
xasprintf(&newvalue, "%s%s", oldvalue, value); case OPTIONS_TABLE_STRING:
o = cmd_set_option_string(self, ctx, oe, oo, value);
break;
case OPTIONS_TABLE_NUMBER:
o = cmd_set_option_number(self, ctx, oe, oo, value);
break;
case OPTIONS_TABLE_KEY:
o = cmd_set_option_key(self, ctx, oe, oo, value);
break;
case OPTIONS_TABLE_COLOUR:
o = cmd_set_option_colour(self, ctx, oe, oo, value);
break;
case OPTIONS_TABLE_ATTRIBUTES:
o = cmd_set_option_attributes(self, ctx, oe, oo, value);
break;
case OPTIONS_TABLE_FLAG:
o = cmd_set_option_flag(self, ctx, oe, oo, value);
break;
case OPTIONS_TABLE_CHOICE:
o = cmd_set_option_choice(self, ctx, oe, oo, value);
break;
}
if (o == NULL)
return (-1);
s = options_table_print_entry(oe, o);
ctx->info(ctx, "set option: %s -> %s", oe->name, s);
return (0);
}
/* Set a string option. */
struct options_entry *
cmd_set_option_string(struct cmd *self, unused struct cmd_ctx *ctx,
const struct options_table_entry *oe, struct options *oo, const char *value)
{
struct args *args = self->args;
struct options_entry *o;
char *oldval, *newval;
if (args_has(args, 'a')) {
oldval = options_get_string(oo, oe->name);
xasprintf(&newval, "%s%s", oldval, value);
} else } else
newvalue = value; newval = xstrdup(value);
o = options_set_string(oo, entry->name, "%s", newvalue); o = options_set_string(oo, oe->name, "%s", newval);
ctx->info(ctx,
"set option: %s -> %s", o->name, cmd_set_option_print(entry, o));
if (newvalue != value) xfree(newval);
xfree(newvalue); return (o);
} }
void /* Set a number option. */
cmd_set_option_number(struct cmd_ctx *ctx, struct options *oo, struct options_entry *
const struct set_option_entry *entry, char *value) cmd_set_option_number(unused struct cmd *self, struct cmd_ctx *ctx,
const struct options_table_entry *oe, struct options *oo, const char *value)
{ {
struct options_entry *o; long long ll;
long long number; const char *errstr;
const char *errstr;
if (value == NULL) { ll = strtonum(value, oe->minimum, oe->maximum, &errstr);
ctx->error(ctx, "empty value");
return;
}
number = strtonum(value, entry->minimum, entry->maximum, &errstr);
if (errstr != NULL) { if (errstr != NULL) {
ctx->error(ctx, "value is %s: %s", errstr, value); ctx->error(ctx, "value is %s: %s", errstr, value);
return; return (NULL);
} }
o = options_set_number(oo, entry->name, number); return (options_set_number(oo, oe->name, ll));
ctx->info(ctx,
"set option: %s -> %s", o->name, cmd_set_option_print(entry, o));
} }
void /* Set a key option. */
cmd_set_option_keys(struct cmd_ctx *ctx, struct options *oo, struct options_entry *
const struct set_option_entry *entry, char *value) cmd_set_option_key(unused struct cmd *self, struct cmd_ctx *ctx,
const struct options_table_entry *oe, struct options *oo, const char *value)
{ {
struct options_entry *o; int key;
struct keylist *keylist;
char *copyvalue, *ptr, *str;
int key;
if (value == NULL) { if ((key = key_string_lookup_string(value)) == KEYC_NONE) {
ctx->error(ctx, "empty value"); ctx->error(ctx, "bad key: %s", value);
return; return (NULL);
} }
keylist = xmalloc(sizeof *keylist); return (options_set_number(oo, oe->name, key));
ARRAY_INIT(keylist);
ptr = copyvalue = xstrdup(value);
while ((str = strsep(&ptr, ",")) != NULL) {
if ((key = key_string_lookup_string(str)) == KEYC_NONE) {
xfree(keylist);
ctx->error(ctx, "unknown key: %s", str);
xfree(copyvalue);
return;
}
ARRAY_ADD(keylist, key);
}
xfree(copyvalue);
o = options_set_data(oo, entry->name, keylist, xfree);
ctx->info(ctx,
"set option: %s -> %s", o->name, cmd_set_option_print(entry, o));
} }
void /* Set a colour option. */
cmd_set_option_colour(struct cmd_ctx *ctx, struct options *oo, struct options_entry *
const struct set_option_entry *entry, char *value) cmd_set_option_colour(unused struct cmd *self, struct cmd_ctx *ctx,
const struct options_table_entry *oe, struct options *oo, const char *value)
{ {
struct options_entry *o; int colour;
int colour;
if (value == NULL) {
ctx->error(ctx, "empty value");
return;
}
if ((colour = colour_fromstring(value)) == -1) { if ((colour = colour_fromstring(value)) == -1) {
ctx->error(ctx, "bad colour: %s", value); ctx->error(ctx, "bad colour: %s", value);
return; return (NULL);
} }
o = options_set_number(oo, entry->name, colour); return (options_set_number(oo, oe->name, colour));
ctx->info(ctx,
"set option: %s -> %s", o->name, cmd_set_option_print(entry, o));
} }
void /* Set an attributes option. */
cmd_set_option_attributes(struct cmd_ctx *ctx, struct options *oo, struct options_entry *
const struct set_option_entry *entry, char *value) cmd_set_option_attributes(unused struct cmd *self, struct cmd_ctx *ctx,
const struct options_table_entry *oe, struct options *oo, const char *value)
{ {
struct options_entry *o; int attr;
int attr;
if (value == NULL) {
ctx->error(ctx, "empty value");
return;
}
if ((attr = attributes_fromstring(value)) == -1) { if ((attr = attributes_fromstring(value)) == -1) {
ctx->error(ctx, "bad attributes: %s", value); ctx->error(ctx, "bad attributes: %s", value);
return; return (NULL);
} }
o = options_set_number(oo, entry->name, attr); return (options_set_number(oo, oe->name, attr));
ctx->info(ctx,
"set option: %s -> %s", o->name, cmd_set_option_print(entry, o));
} }
void /* Set a flag option. */
cmd_set_option_flag(struct cmd_ctx *ctx, struct options *oo, struct options_entry *
const struct set_option_entry *entry, char *value) cmd_set_option_flag(unused struct cmd *self, struct cmd_ctx *ctx,
const struct options_table_entry *oe, struct options *oo, const char *value)
{ {
struct options_entry *o; int flag;
int flag;
if (value == NULL || *value == '\0') if (value == NULL || *value == '\0')
flag = !options_get_number(oo, entry->name); flag = !options_get_number(oo, oe->name);
else { else {
if ((value[0] == '1' && value[1] == '\0') || if ((value[0] == '1' && value[1] == '\0') ||
strcasecmp(value, "on") == 0 || strcasecmp(value, "on") == 0 ||
@@ -513,46 +363,37 @@ cmd_set_option_flag(struct cmd_ctx *ctx, struct options *oo,
flag = 0; flag = 0;
else { else {
ctx->error(ctx, "bad value: %s", value); ctx->error(ctx, "bad value: %s", value);
return; return (NULL);
} }
} }
o = options_set_number(oo, entry->name, flag); return (options_set_number(oo, oe->name, flag));
ctx->info(ctx,
"set option: %s -> %s", o->name, cmd_set_option_print(entry, o));
} }
void /* Set a choice option. */
cmd_set_option_choice(struct cmd_ctx *ctx, struct options *oo, struct options_entry *
const struct set_option_entry *entry, char *value) cmd_set_option_choice(unused struct cmd *self, struct cmd_ctx *ctx,
const struct options_table_entry *oe, struct options *oo, const char *value)
{ {
struct options_entry *o; const char **choicep;
const char **choicep; int n, choice = -1;
int n, choice = -1;
if (value == NULL) {
ctx->error(ctx, "empty value");
return;
}
n = 0; n = 0;
for (choicep = entry->choices; *choicep != NULL; choicep++) { for (choicep = oe->choices; *choicep != NULL; choicep++) {
n++; n++;
if (strncmp(*choicep, value, strlen(value)) != 0) if (strncmp(*choicep, value, strlen(value)) != 0)
continue; continue;
if (choice != -1) { if (choice != -1) {
ctx->error(ctx, "ambiguous option value: %s", value); ctx->error(ctx, "ambiguous value: %s", value);
return; return (NULL);
} }
choice = n - 1; choice = n - 1;
} }
if (choice == -1) { if (choice == -1) {
ctx->error(ctx, "unknown option value: %s", value); ctx->error(ctx, "unknown value: %s", value);
return; return (NULL);
} }
o = options_set_number(oo, entry->name, choice); return (options_set_number(oo, oe->name, choice));
ctx->info(ctx,
"set option: %s -> %s", o->name, cmd_set_option_print(entry, o));
} }

View File

@@ -1,47 +0,0 @@
/* $Id: cmd-set-window-option.c,v 1.43 2009-12-04 22:11:23 tcunha Exp $ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Set a window option. This is just an alias for set-option -w.
*/
int cmd_set_window_option_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_set_window_option_entry = {
"set-window-option", "setw",
"[-agu] " CMD_TARGET_WINDOW_USAGE " option [value]",
CMD_ARG12, "agu",
NULL,
cmd_target_parse,
cmd_set_window_option_exec,
cmd_target_free,
cmd_target_print
};
int
cmd_set_window_option_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
cmd_set_flag(&data->chflags, 'w');
return (cmd_set_option_entry.exec(self, ctx));
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-show-buffer.c,v 1.12 2009-12-04 22:14:47 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -21,46 +21,54 @@
#include "tmux.h" #include "tmux.h"
/* /*
* Show a session paste buffer. * Show a paste buffer.
*/ */
int cmd_show_buffer_exec(struct cmd *, struct cmd_ctx *); int cmd_show_buffer_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_show_buffer_entry = { const struct cmd_entry cmd_show_buffer_entry = {
"show-buffer", "showb", "show-buffer", "showb",
CMD_BUFFER_SESSION_USAGE, "b:", 0, 0,
0, "", CMD_BUFFER_USAGE,
cmd_buffer_init, 0,
cmd_buffer_parse, NULL,
cmd_show_buffer_exec, NULL,
cmd_buffer_free, cmd_show_buffer_exec
cmd_buffer_print
}; };
int int
cmd_show_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_show_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_buffer_data *data = self->data; struct args *args = self->args;
struct session *s; struct session *s;
struct paste_buffer *pb; struct paste_buffer *pb;
char *in, *buf, *ptr; int buffer;
char *in, *buf, *ptr, *cause;
size_t size, len; size_t size, len;
u_int width; u_int width;
if ((s = cmd_find_session(ctx, data->target)) == NULL) if ((s = cmd_find_session(ctx, NULL, 0)) == NULL)
return (-1); return (-1);
if (data->buffer == -1) { if (!args_has(args, 'b')) {
if ((pb = paste_get_top(&s->buffers)) == NULL) { if ((pb = paste_get_top(&global_buffers)) == NULL) {
ctx->error(ctx, "no buffers"); ctx->error(ctx, "no buffers");
return (-1); return (-1);
} }
} else if ((pb = paste_get_index(&s->buffers, data->buffer)) == NULL) { } else {
ctx->error(ctx, "no buffer %d", data->buffer); buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
return (-1); if (cause != NULL) {
ctx->error(ctx, "buffer %s", cause);
xfree(cause);
return (-1);
}
pb = paste_get_index(&global_buffers, buffer);
if (pb == NULL) {
ctx->error(ctx, "no buffer %d", buffer);
return (-1);
}
} }
if (pb == NULL)
return (0);
size = pb->size; size = pb->size;
if (size > SIZE_MAX / 4 - 1) if (size > SIZE_MAX / 4 - 1)

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-show-environment.c,v 1.2 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,27 +31,26 @@ int cmd_show_environment_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_show_environment_entry = { const struct cmd_entry cmd_show_environment_entry = {
"show-environment", "showenv", "show-environment", "showenv",
"gt:", 0, 0,
"[-g] " CMD_TARGET_SESSION_USAGE, "[-g] " CMD_TARGET_SESSION_USAGE,
0, "g", 0,
cmd_target_init, NULL,
cmd_target_parse, NULL,
cmd_show_environment_exec, cmd_show_environment_exec
cmd_target_free,
cmd_target_print
}; };
int int
cmd_show_environment_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_show_environment_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct session *s; struct session *s;
struct environ *env; struct environ *env;
struct environ_entry *envent; struct environ_entry *envent;
if (cmd_check_flag(data->chflags, 'g')) if (args_has(self->args, 'g'))
env = &global_environ; env = &global_environ;
else { else {
if ((s = cmd_find_session(ctx, data->target)) == NULL) if ((s = cmd_find_session(ctx, args_get(args, 't'), 0)) == NULL)
return (-1); return (-1);
env = &s->environ; env = &s->environ;
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-show-messages.c,v 1.2 2009-12-04 22:14:47 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,25 +31,24 @@ int cmd_show_messages_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_show_messages_entry = { const struct cmd_entry cmd_show_messages_entry = {
"show-messages", "showmsgs", "show-messages", "showmsgs",
"t:", 0, 0,
CMD_TARGET_CLIENT_USAGE, CMD_TARGET_CLIENT_USAGE,
0, "", 0,
cmd_target_init, NULL,
cmd_target_parse, NULL,
cmd_show_messages_exec, cmd_show_messages_exec
cmd_target_free,
cmd_target_print
}; };
int int
cmd_show_messages_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_show_messages_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct client *c; struct client *c;
struct message_entry *msg; struct message_entry *msg;
char *tim; char *tim;
u_int i; u_int i;
if ((c = cmd_find_client(ctx, data->target)) == NULL) if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL)
return (-1); return (-1);
for (i = 0; i < ARRAY_LENGTH(&c->message_log); i++) { for (i = 0; i < ARRAY_LENGTH(&c->message_log); i++) {

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-show-options.c,v 1.21 2009-12-10 16:59:02 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,57 +31,66 @@ int cmd_show_options_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_show_options_entry = { const struct cmd_entry cmd_show_options_entry = {
"show-options", "show", "show-options", "show",
"gst:w", 0, 0,
"[-gsw] [-t target-session|target-window]", "[-gsw] [-t target-session|target-window]",
0, "gsw", 0,
cmd_target_init, NULL,
cmd_target_parse, NULL,
cmd_show_options_exec, cmd_show_options_exec
cmd_target_free, };
cmd_target_print
const struct cmd_entry cmd_show_window_options_entry = {
"show-window-options", "showw",
"gt:", 0, 0,
"[-g] " CMD_TARGET_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_show_options_exec
}; };
int int
cmd_show_options_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_show_options_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
const struct set_option_entry *table; const struct options_table_entry *table, *oe;
struct session *s; struct session *s;
struct winlink *wl; struct winlink *wl;
struct options *oo; struct options *oo;
struct options_entry *o; struct options_entry *o;
const struct set_option_entry *entry; const char *optval;
const char *optval;
if (cmd_check_flag(data->chflags, 's')) { if (args_has(self->args, 's')) {
oo = &global_options; oo = &global_options;
table = set_option_table; table = server_options_table;
} else if (cmd_check_flag(data->chflags, 'w')) { } else if (args_has(self->args, 'w') ||
table = set_window_option_table; self->entry == &cmd_show_window_options_entry) {
if (cmd_check_flag(data->chflags, 'g')) table = window_options_table;
if (args_has(self->args, 'g'))
oo = &global_w_options; oo = &global_w_options;
else { else {
wl = cmd_find_window(ctx, data->target, NULL); wl = cmd_find_window(ctx, args_get(args, 't'), NULL);
if (wl == NULL) if (wl == NULL)
return (-1); return (-1);
oo = &wl->window->options; oo = &wl->window->options;
} }
} else { } else {
table = set_session_option_table; table = session_options_table;
if (cmd_check_flag(data->chflags, 'g')) if (args_has(self->args, 'g'))
oo = &global_s_options; oo = &global_s_options;
else { else {
s = cmd_find_session(ctx, data->target); s = cmd_find_session(ctx, args_get(args, 't'), 0);
if (s == NULL) if (s == NULL)
return (-1); return (-1);
oo = &s->options; oo = &s->options;
} }
} }
for (entry = table; entry->name != NULL; entry++) { for (oe = table; oe->name != NULL; oe++) {
if ((o = options_find1(oo, entry->name)) == NULL) if ((o = options_find1(oo, oe->name)) == NULL)
continue; continue;
optval = cmd_set_option_print(entry, o); optval = options_table_print_entry(oe, o);
ctx->print(ctx, "%s %s", entry->name, optval); ctx->print(ctx, "%s %s", oe->name, optval);
} }
return (0); return (0);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-source-file.c,v 1.13 2010-02-08 18:29:32 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2008 Tiago Cunha <me@tiagocunha.org> * Copyright (c) 2008 Tiago Cunha <me@tiagocunha.org>
@@ -24,108 +24,51 @@
* Sources a configuration file. * Sources a configuration file.
*/ */
int cmd_source_file_parse(struct cmd *, int, char **, char **);
int cmd_source_file_exec(struct cmd *, struct cmd_ctx *); int cmd_source_file_exec(struct cmd *, struct cmd_ctx *);
void cmd_source_file_free(struct cmd *);
void cmd_source_file_init(struct cmd *, int);
size_t cmd_source_file_print(struct cmd *, char *, size_t);
struct cmd_source_file_data {
char *path;
};
const struct cmd_entry cmd_source_file_entry = { const struct cmd_entry cmd_source_file_entry = {
"source-file", "source", "source-file", "source",
"", 1, 1,
"path", "path",
0, "", 0,
cmd_source_file_init, NULL,
cmd_source_file_parse, NULL,
cmd_source_file_exec, cmd_source_file_exec
cmd_source_file_free,
cmd_source_file_print
}; };
/* ARGSUSED */
void
cmd_source_file_init(struct cmd *self, unused int arg)
{
struct cmd_source_file_data *data;
self->data = data = xmalloc(sizeof *data);
data->path = NULL;
}
int
cmd_source_file_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_source_file_data *data;
int opt;
self->entry->init(self, KEYC_NONE);
data = self->data;
while ((opt = getopt(argc, argv, "")) != -1) {
switch (opt) {
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 1)
goto usage;
data->path = xstrdup(argv[0]);
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
self->entry->free(self);
return (-1);
}
int int
cmd_source_file_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_source_file_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_source_file_data *data = self->data; struct args *args = self->args;
struct causelist causes; struct causelist causes;
char *cause; char *cause;
u_int i; struct window_pane *wp;
int retval;
u_int i;
ARRAY_INIT(&causes); ARRAY_INIT(&causes);
if (load_cfg(data->path, ctx, &causes) != 0) {
retval = load_cfg(args->argv[0], ctx, &causes);
if (ARRAY_EMPTY(&causes))
return (retval);
if (retval == 1 && !RB_EMPTY(&sessions) && ctx->cmdclient != NULL) {
wp = RB_MIN(sessions, &sessions)->curw->window->active;
window_pane_set_mode(wp, &window_copy_mode);
window_copy_init_for_output(wp);
for (i = 0; i < ARRAY_LENGTH(&causes); i++) {
cause = ARRAY_ITEM(&causes, i);
window_copy_add(wp, "%s", cause);
xfree(cause);
}
} else {
for (i = 0; i < ARRAY_LENGTH(&causes); i++) { for (i = 0; i < ARRAY_LENGTH(&causes); i++) {
cause = ARRAY_ITEM(&causes, i); cause = ARRAY_ITEM(&causes, i);
ctx->print(ctx, "%s", cause); ctx->print(ctx, "%s", cause);
xfree(cause); xfree(cause);
} }
ARRAY_FREE(&causes);
} }
ARRAY_FREE(&causes);
return (0); return (retval);
}
void
cmd_source_file_free(struct cmd *self)
{
struct cmd_source_file_data *data = self->data;
if (data->path != NULL)
xfree(data->path);
xfree(data);
}
size_t
cmd_source_file_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_source_file_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->path != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->path);
return (off);
} }

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-split-window.c,v 1.34 2010-01-08 16:31:35 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,137 +27,44 @@
* Split a window (add a new pane). * Split a window (add a new pane).
*/ */
int cmd_split_window_parse(struct cmd *, int, char **, char **); void cmd_split_window_key_binding(struct cmd *, int);
int cmd_split_window_exec(struct cmd *, struct cmd_ctx *); int cmd_split_window_exec(struct cmd *, struct cmd_ctx *);
void cmd_split_window_free(struct cmd *);
void cmd_split_window_init(struct cmd *, int);
size_t cmd_split_window_print(struct cmd *, char *, size_t);
struct cmd_split_window_data {
char *target;
char *cmd;
int flag_detached;
int flag_horizontal;
int percentage;
int size;
};
const struct cmd_entry cmd_split_window_entry = { const struct cmd_entry cmd_split_window_entry = {
"split-window", "splitw", "split-window", "splitw",
"[-dhv] [-p percentage|-l size] [-t target-pane] [command]", "dl:hp:Pt:v", 0, 1,
0, "", "[-dhvP] [-p percentage|-l size] [-t target-pane] [command]",
cmd_split_window_init, 0,
cmd_split_window_parse, cmd_split_window_key_binding,
cmd_split_window_exec, NULL,
cmd_split_window_free, cmd_split_window_exec
cmd_split_window_print
}; };
void void
cmd_split_window_init(struct cmd *self, int key) cmd_split_window_key_binding(struct cmd *self, int key)
{ {
struct cmd_split_window_data *data; self->args = args_create(0);
if (key == '%')
self->data = data = xmalloc(sizeof *data); args_set(self->args, 'h', NULL);
data->target = NULL;
data->cmd = NULL;
data->flag_detached = 0;
data->flag_horizontal = 0;
data->percentage = -1;
data->size = -1;
switch (key) {
case '%':
data->flag_horizontal = 1;
break;
case '"':
data->flag_horizontal = 0;
break;
}
}
int
cmd_split_window_parse(struct cmd *self, int argc, char **argv, char **cause)
{
struct cmd_split_window_data *data;
int opt;
const char *errstr;
self->entry->init(self, KEYC_NONE);
data = self->data;
while ((opt = getopt(argc, argv, "dhl:p:t:v")) != -1) {
switch (opt) {
case 'd':
data->flag_detached = 1;
break;
case 'h':
data->flag_horizontal = 1;
break;
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
case 'l':
if (data->percentage != -1 || data->size != -1)
break;
data->size = strtonum(optarg, 1, INT_MAX, &errstr);
if (errstr != NULL) {
xasprintf(cause, "size %s", errstr);
goto error;
}
break;
case 'p':
if (data->size != -1 || data->percentage != -1)
break;
data->percentage = strtonum(optarg, 1, 100, &errstr);
if (errstr != NULL) {
xasprintf(cause, "percentage %s", errstr);
goto error;
}
break;
case 'v':
data->flag_horizontal = 0;
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 0 && argc != 1)
goto usage;
if (argc == 1)
data->cmd = xstrdup(argv[0]);
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
error:
self->entry->free(self);
return (-1);
} }
int int
cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_split_window_data *data = self->data; struct args *args = self->args;
struct session *s; struct session *s;
struct winlink *wl; struct winlink *wl;
struct window *w; struct window *w;
struct window_pane *wp, *new_wp = NULL; struct window_pane *wp, *new_wp = NULL;
struct environ env; struct environ env;
char *cmd, *cwd, *cause; const char *cmd, *cwd, *shell;
const char *shell; char *cause, *new_cause;
u_int hlimit; u_int hlimit, paneidx;
int size; int size, percentage;
enum layout_type type; enum layout_type type;
struct layout_cell *lc; struct layout_cell *lc;
if ((wl = cmd_find_pane(ctx, data->target, &s, &wp)) == NULL) if ((wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp)) == NULL)
return (-1); return (-1);
w = wl->window; w = wl->window;
@@ -166,26 +73,37 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
environ_copy(&s->environ, &env); environ_copy(&s->environ, &env);
server_fill_environ(s, &env); server_fill_environ(s, &env);
cmd = data->cmd; if (args->argc == 0)
if (cmd == NULL)
cmd = options_get_string(&s->options, "default-command"); cmd = options_get_string(&s->options, "default-command");
if (ctx->cmdclient == NULL || ctx->cmdclient->cwd == NULL)
cwd = options_get_string(&s->options, "default-path");
else else
cwd = ctx->cmdclient->cwd; cmd = args->argv[0];
cwd = cmd_get_default_path(ctx);
type = LAYOUT_TOPBOTTOM; type = LAYOUT_TOPBOTTOM;
if (data->flag_horizontal) if (args_has(args, 'h'))
type = LAYOUT_LEFTRIGHT; type = LAYOUT_LEFTRIGHT;
size = -1; size = -1;
if (data->size != -1) if (args_has(args, 'l')) {
size = data->size; size = args_strtonum(args, 'l', 0, INT_MAX, &cause);
else if (data->percentage != -1) { if (cause != NULL) {
xasprintf(&new_cause, "size %s", cause);
xfree(cause);
cause = new_cause;
goto error;
}
} else if (args_has(args, 'p')) {
percentage = args_strtonum(args, 'p', 0, INT_MAX, &cause);
if (cause != NULL) {
xasprintf(&new_cause, "percentage %s", cause);
xfree(cause);
cause = new_cause;
goto error;
}
if (type == LAYOUT_TOPBOTTOM) if (type == LAYOUT_TOPBOTTOM)
size = (wp->sy * data->percentage) / 100; size = (wp->sy * percentage) / 100;
else else
size = (wp->sx * data->percentage) / 100; size = (wp->sx * percentage) / 100;
} }
hlimit = options_get_number(&s->options, "history-limit"); hlimit = options_get_number(&s->options, "history-limit");
@@ -205,7 +123,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
server_redraw_window(w); server_redraw_window(w);
if (!data->flag_detached) { 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);
server_redraw_session(s); server_redraw_session(s);
@@ -213,6 +131,12 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
server_status_session(s); server_status_session(s);
environ_free(&env); environ_free(&env);
if (args_has(args, 'P')) {
if (window_pane_index(new_wp, &paneidx) != 0)
fatalx("index not found");
ctx->print(ctx, "%s:%u.%u", s->name, wl->idx, paneidx);
}
return (0); return (0);
error: error:
@@ -223,41 +147,3 @@ error:
xfree(cause); xfree(cause);
return (-1); return (-1);
} }
void
cmd_split_window_free(struct cmd *self)
{
struct cmd_split_window_data *data = self->data;
if (data->target != NULL)
xfree(data->target);
if (data->cmd != NULL)
xfree(data->cmd);
xfree(data);
}
size_t
cmd_split_window_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_split_window_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->flag_detached)
off += xsnprintf(buf + off, len - off, " -d");
if (off < len && data->flag_horizontal)
off += xsnprintf(buf + off, len - off, " -h");
if (off < len && data->size > 0)
off += xsnprintf(buf + off, len - off, " -l %d", data->size);
if (off < len && data->percentage > 0) {
off += xsnprintf(
buf + off, len - off, " -p %d", data->percentage);
}
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
if (off < len && data->cmd != NULL)
off += cmd_prarg(buf + off, len - off, " ", data->cmd);
return (off);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-start-server.c,v 1.10 2009-11-28 14:50:36 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,13 +28,12 @@ int cmd_start_server_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_start_server_entry = { const struct cmd_entry cmd_start_server_entry = {
"start-server", "start", "start-server", "start",
"", 0, 0,
"", "",
CMD_STARTSERVER, "", CMD_STARTSERVER,
NULL, NULL,
NULL, NULL,
cmd_start_server_exec, cmd_start_server_exec
NULL,
NULL
}; };
/* ARGSUSED */ /* ARGSUSED */

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-string.c,v 1.31 2010-02-26 13:27:38 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -247,9 +247,10 @@ error:
char * char *
cmd_string_variable(const char *s, size_t *p) cmd_string_variable(const char *s, size_t *p)
{ {
int ch, fch; int ch, fch;
char *buf, *t; char *buf, *t;
size_t len; size_t len;
struct environ_entry *envent;
#define cmd_string_first(ch) ((ch) == '_' || \ #define cmd_string_first(ch) ((ch) == '_' || \
((ch) >= 'a' && (ch) <= 'z') || ((ch) >= 'A' && (ch) <= 'Z')) ((ch) >= 'a' && (ch) <= 'z') || ((ch) >= 'A' && (ch) <= 'Z'))
@@ -301,12 +302,11 @@ cmd_string_variable(const char *s, size_t *p)
buf = xrealloc(buf, 1, len + 1); buf = xrealloc(buf, 1, len + 1);
buf[len] = '\0'; buf[len] = '\0';
if ((t = getenv(buf)) == NULL) { envent = environ_find(&global_environ, buf);
xfree(buf);
return (xstrdup(""));
}
xfree(buf); xfree(buf);
return (xstrdup(t)); if (envent == NULL)
return (xstrdup(""));
return (xstrdup(envent->value));
error: error:
if (buf != NULL) if (buf != NULL)
@@ -317,15 +317,17 @@ error:
char * char *
cmd_string_expand_tilde(const char *s, size_t *p) cmd_string_expand_tilde(const char *s, size_t *p)
{ {
struct passwd *pw; struct passwd *pw;
char *home, *path, *username; struct environ_entry *envent;
char *home, *path, *username;
home = NULL; home = NULL;
if (cmd_string_getc(s, p) == '/') { if (cmd_string_getc(s, p) == '/') {
if ((home = getenv("HOME")) == NULL || *home == '\0') { envent = environ_find(&global_environ, "HOME");
if ((pw = getpwuid(getuid())) != NULL) if (envent != NULL && *envent->value != '\0')
home = pw->pw_dir; home = envent->value;
} else if ((pw = getpwuid(getuid())) != NULL)
home = pw->pw_dir;
} else { } else {
cmd_string_ungetc(p); cmd_string_ungetc(p);
if ((username = cmd_string_string(s, p, '/', 0)) == NULL) if ((username = cmd_string_string(s, p, '/', 0)) == NULL)

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-suspend-client.c,v 1.5 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -29,29 +29,23 @@
int cmd_suspend_client_exec(struct cmd *, struct cmd_ctx *); int cmd_suspend_client_exec(struct cmd *, struct cmd_ctx *);
struct cmd_suspend_client_data {
char *name;
char *target;
};
const struct cmd_entry cmd_suspend_client_entry = { const struct cmd_entry cmd_suspend_client_entry = {
"suspend-client", "suspendc", "suspend-client", "suspendc",
"[-c target-client]", "t:", 0, 0,
0, "", CMD_TARGET_CLIENT_USAGE,
cmd_target_init, 0,
cmd_target_parse, NULL,
cmd_suspend_client_exec, NULL,
cmd_target_free, cmd_suspend_client_exec
cmd_target_print
}; };
int int
cmd_suspend_client_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_suspend_client_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct client *c; struct client *c;
if ((c = cmd_find_client(ctx, data->target)) == NULL) if ((c = cmd_find_client(ctx, args_get(args, 't'))) == NULL)
return (-1); return (-1);
tty_stop_tty(&c->tty); tty_stop_tty(&c->tty);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-swap-pane.c,v 1.15 2009-12-04 22:14:47 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -26,66 +26,58 @@
* Swap two panes. * Swap two panes.
*/ */
void cmd_swap_pane_init(struct cmd *, int); void cmd_swap_pane_key_binding(struct cmd *, int);
int cmd_swap_pane_exec(struct cmd *, struct cmd_ctx *); int cmd_swap_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_swap_pane_entry = { const struct cmd_entry cmd_swap_pane_entry = {
"swap-pane", "swapp", "swap-pane", "swapp",
"dDs:t:U", 0, 0,
"[-dDU] " CMD_SRCDST_PANE_USAGE, "[-dDU] " CMD_SRCDST_PANE_USAGE,
0, "dDU", 0,
cmd_swap_pane_init, cmd_swap_pane_key_binding,
cmd_srcdst_parse, NULL,
cmd_swap_pane_exec, cmd_swap_pane_exec
cmd_srcdst_free,
cmd_srcdst_print
}; };
void void
cmd_swap_pane_init(struct cmd *self, int key) cmd_swap_pane_key_binding(struct cmd *self, int key)
{ {
struct cmd_target_data *data; self->args = args_create(0);
cmd_srcdst_init(self, key);
data = self->data;
if (key == '{') if (key == '{')
cmd_set_flag(&data->chflags, 'U'); args_set(self->args, 'U', NULL);
else if (key == '}') else if (key == '}')
cmd_set_flag(&data->chflags, 'D'); args_set(self->args, 'D', NULL);
} }
int int
cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_srcdst_data *data = self->data; struct args *args = self->args;
struct winlink *src_wl, *dst_wl; struct winlink *src_wl, *dst_wl;
struct window *src_w, *dst_w; struct window *src_w, *dst_w;
struct window_pane *tmp_wp, *src_wp, *dst_wp; struct window_pane *tmp_wp, *src_wp, *dst_wp;
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;
if (data == NULL) dst_wl = cmd_find_pane(ctx, args_get(args, 't'), NULL, &dst_wp);
return (0); if (dst_wl == NULL)
if ((dst_wl = cmd_find_pane(ctx, data->dst, NULL, &dst_wp)) == NULL)
return (-1); return (-1);
dst_w = dst_wl->window; dst_w = dst_wl->window;
if (data->src == NULL) { if (!args_has(args, 's')) {
src_w = dst_w; src_w = dst_w;
if (cmd_check_flag(data->chflags, 'D')) { if (args_has(self->args, 'D')) {
src_wp = TAILQ_NEXT(dst_wp, entry); src_wp = TAILQ_NEXT(dst_wp, entry);
if (src_wp == NULL) if (src_wp == NULL)
src_wp = TAILQ_FIRST(&dst_w->panes); src_wp = TAILQ_FIRST(&dst_w->panes);
} else if (cmd_check_flag(data->chflags, 'U')) { } else if (args_has(self->args, 'U')) {
src_wp = TAILQ_PREV(dst_wp, window_panes, entry); src_wp = TAILQ_PREV(dst_wp, window_panes, entry);
if (src_wp == NULL) if (src_wp == NULL)
src_wp = TAILQ_LAST(&dst_w->panes, window_panes); src_wp = TAILQ_LAST(&dst_w->panes, window_panes);
} else } else
return (0); return (0);
} else { } else {
src_wl = cmd_find_pane(ctx, data->src, NULL, &src_wp); src_wl = cmd_find_pane(ctx, args_get(args, 's'), NULL, &src_wp);
if (src_wl == NULL) if (src_wl == NULL)
return (-1); return (-1);
src_w = src_wl->window; src_w = src_wl->window;
@@ -121,7 +113,7 @@ cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
dst_wp->xoff = xoff; dst_wp->yoff = yoff; dst_wp->xoff = xoff; dst_wp->yoff = yoff;
window_pane_resize(dst_wp, sx, sy); window_pane_resize(dst_wp, sx, sy);
if (!cmd_check_flag(data->chflags, 'd')) { if (!args_has(self->args, 'd')) {
if (src_w != dst_w) { if (src_w != dst_w) {
window_set_active_pane(src_w, dst_wp); window_set_active_pane(src_w, dst_wp);
window_set_active_pane(dst_w, src_wp); window_set_active_pane(dst_w, src_wp);
@@ -137,6 +129,12 @@ cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
if (dst_w->active == dst_wp) if (dst_w->active == dst_wp)
window_set_active_pane(dst_w, src_wp); window_set_active_pane(dst_w, src_wp);
} }
if (src_w != dst_w) {
if (src_w->last == src_wp)
src_w->last = NULL;
if (dst_w->last == dst_wp)
dst_w->last = NULL;
}
server_redraw_window(src_w); server_redraw_window(src_w);
server_redraw_window(dst_w); server_redraw_window(dst_w);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-swap-window.c,v 1.19 2009-11-14 17:56:39 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -30,27 +30,29 @@ int cmd_swap_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_swap_window_entry = { const struct cmd_entry cmd_swap_window_entry = {
"swap-window", "swapw", "swap-window", "swapw",
"ds:t:", 0, 0,
"[-d] " CMD_SRCDST_WINDOW_USAGE, "[-d] " CMD_SRCDST_WINDOW_USAGE,
0, "d", 0,
cmd_srcdst_init, NULL,
cmd_srcdst_parse, NULL,
cmd_swap_window_exec, cmd_swap_window_exec
cmd_srcdst_free,
cmd_srcdst_print
}; };
int int
cmd_swap_window_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_swap_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_srcdst_data *data = self->data; struct args *args = self->args;
const char *target_src, *target_dst;
struct session *src, *dst; struct session *src, *dst;
struct session_group *sg_src, *sg_dst; struct session_group *sg_src, *sg_dst;
struct winlink *wl_src, *wl_dst; struct winlink *wl_src, *wl_dst;
struct window *w; struct window *w;
if ((wl_src = cmd_find_window(ctx, data->src, &src)) == NULL) target_src = args_get(args, 's');
if ((wl_src = cmd_find_window(ctx, target_src, &src)) == NULL)
return (-1); return (-1);
if ((wl_dst = cmd_find_window(ctx, data->dst, &dst)) == NULL) target_dst = args_get(args, 't');
if ((wl_dst = cmd_find_window(ctx, target_dst, &dst)) == NULL)
return (-1); return (-1);
sg_src = session_group_find(src); sg_src = session_group_find(src);
@@ -68,7 +70,7 @@ cmd_swap_window_exec(struct cmd *self, struct cmd_ctx *ctx)
wl_dst->window = wl_src->window; wl_dst->window = wl_src->window;
wl_src->window = w; wl_src->window = w;
if (!cmd_check_flag(data->chflags, 'd')) { if (!args_has(self->args, 'd')) {
session_select(dst, wl_dst->idx); session_select(dst, wl_dst->idx);
if (src != dst) if (src != dst)
session_select(src, wl_src->idx); session_select(src, wl_src->idx);

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-switch-client.c,v 1.19 2010-01-25 17:12:44 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -27,112 +27,88 @@
* Switch client to a different session. * Switch client to a different session.
*/ */
int cmd_switch_client_parse(struct cmd *, int, char **, char **); void cmd_switch_client_key_binding(struct cmd *, int);
int cmd_switch_client_exec(struct cmd *, struct cmd_ctx *); int cmd_switch_client_exec(struct cmd *, struct cmd_ctx *);
void cmd_switch_client_free(struct cmd *);
size_t cmd_switch_client_print(struct cmd *, char *, size_t);
struct cmd_switch_client_data {
char *name;
char *target;
};
const struct cmd_entry cmd_switch_client_entry = { const struct cmd_entry cmd_switch_client_entry = {
"switch-client", "switchc", "switch-client", "switchc",
"[-c target-client] [-t target-session]", "lc:npt:r", 0, 0,
0, "", "[-lnpr] [-c target-client] [-t target-session]",
CMD_READONLY,
cmd_switch_client_key_binding,
NULL, NULL,
cmd_switch_client_parse, cmd_switch_client_exec
cmd_switch_client_exec,
cmd_switch_client_free,
cmd_switch_client_print
}; };
int void
cmd_switch_client_parse(struct cmd *self, int argc, char **argv, char **cause) cmd_switch_client_key_binding(struct cmd *self, int key)
{ {
struct cmd_switch_client_data *data; self->args = args_create(0);
int opt; switch (key) {
case '(':
self->data = data = xmalloc(sizeof *data); args_set(self->args, 'p', NULL);
data->name = NULL; break;
data->target = NULL; case ')':
args_set(self->args, 'n', NULL);
while ((opt = getopt(argc, argv, "c:t:")) != -1) { break;
switch (opt) { case 'L':
case 'c': args_set(self->args, 'l', NULL);
if (data->name == NULL) break;
data->name = xstrdup(optarg);
break;
case 't':
if (data->target == NULL)
data->target = xstrdup(optarg);
break;
default:
goto usage;
}
} }
argc -= optind;
argv += optind;
if (argc != 0)
goto usage;
return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
self->entry->free(self);
return (-1);
} }
int int
cmd_switch_client_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_switch_client_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_switch_client_data *data = self->data; struct args *args = self->args;
struct client *c; struct client *c;
struct session *s; struct session *s;
if (data == NULL) if ((c = cmd_find_client(ctx, args_get(args, 'c'))) == NULL)
return (0);
if ((c = cmd_find_client(ctx, data->name)) == NULL)
return (-1);
if ((s = cmd_find_session(ctx, data->target)) == NULL)
return (-1); return (-1);
if (args_has(args, 'r')) {
if (c->flags & CLIENT_READONLY) {
c->flags &= ~CLIENT_READONLY;
ctx->info(ctx, "made client writable");
} else {
c->flags |= CLIENT_READONLY;
ctx->info(ctx, "made client read-only");
}
}
s = NULL;
if (args_has(args, 'n')) {
if ((s = session_next_session(c->session)) == NULL) {
ctx->error(ctx, "can't find next session");
return (-1);
}
} else if (args_has(args, 'p')) {
if ((s = session_previous_session(c->session)) == NULL) {
ctx->error(ctx, "can't find previous session");
return (-1);
}
} else if (args_has(args, 'l')) {
if (c->last_session != NULL && session_alive(c->last_session))
s = c->last_session;
if (s == NULL) {
ctx->error(ctx, "can't find last session");
return (-1);
}
} else
s = cmd_find_session(ctx, args_get(args, 't'), 0);
if (s == NULL)
return (-1);
if (c->session != NULL)
c->last_session = c->session;
c->session = s; c->session = s;
session_update_activity(s);
recalculate_sizes(); recalculate_sizes();
server_check_unattached();
server_redraw_client(c); server_redraw_client(c);
s->curw->flags &= ~WINLINK_ALERTFLAGS;
return (0); return (0);
} }
void
cmd_switch_client_free(struct cmd *self)
{
struct cmd_switch_client_data *data = self->data;
if (data->name != NULL)
xfree(data->name);
if (data->target != NULL)
xfree(data->target);
xfree(data);
}
size_t
cmd_switch_client_print(struct cmd *self, char *buf, size_t len)
{
struct cmd_switch_client_data *data = self->data;
size_t off = 0;
off += xsnprintf(buf, len, "%s", self->entry->name);
if (data == NULL)
return (off);
if (off < len && data->name != NULL)
off += cmd_prarg(buf + off, len - off, " -c ", data->name);
if (off < len && data->target != NULL)
off += cmd_prarg(buf + off, len - off, " -t ", data->target);
return (off);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-unbind-key.c,v 1.22 2010-01-25 17:12:44 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -24,120 +24,80 @@
* Unbind key from command. * Unbind key from command.
*/ */
int cmd_unbind_key_parse(struct cmd *, int, char **, char **); int cmd_unbind_key_check(struct args *);
int cmd_unbind_key_exec(struct cmd *, struct cmd_ctx *); int cmd_unbind_key_exec(struct cmd *, struct cmd_ctx *);
void cmd_unbind_key_free(struct cmd *);
int cmd_unbind_key_table(struct cmd *, struct cmd_ctx *); int cmd_unbind_key_table(struct cmd *, struct cmd_ctx *, int);
struct cmd_unbind_key_data {
int key;
int command_key;
char *tablename;
};
const struct cmd_entry cmd_unbind_key_entry = { const struct cmd_entry cmd_unbind_key_entry = {
"unbind-key", "unbind", "unbind-key", "unbind",
"[-cn] [-t key-table] key", "acnt:", 0, 1,
0, "", "[-acn] [-t key-table] key",
0,
NULL, NULL,
cmd_unbind_key_parse, cmd_unbind_key_check,
cmd_unbind_key_exec, cmd_unbind_key_exec
cmd_unbind_key_free,
NULL
}; };
int int
cmd_unbind_key_parse(struct cmd *self, int argc, char **argv, char **cause) cmd_unbind_key_check(struct args *args)
{ {
struct cmd_unbind_key_data *data; if (args_has(args, 'a') && (args->argc != 0 || args_has(args, 't')))
int opt, no_prefix = 0; return (-1);
if (!args_has(args, 'a') && args->argc != 1)
self->data = data = xmalloc(sizeof *data); return (-1);
data->command_key = 0;
data->tablename = NULL;
while ((opt = getopt(argc, argv, "cnt:")) != -1) {
switch (opt) {
case 'c':
data->command_key = 1;
break;
case 'n':
no_prefix = 1;
break;
case 't':
if (data->tablename == NULL)
data->tablename = xstrdup(optarg);
break;
default:
goto usage;
}
}
argc -= optind;
argv += optind;
if (argc != 1)
goto usage;
if ((data->key = key_string_lookup_string(argv[0])) == KEYC_NONE) {
xasprintf(cause, "unknown key: %s", argv[0]);
goto error;
}
if (!no_prefix)
data->key |= KEYC_PREFIX;
return (0); return (0);
usage:
xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
error:
xfree(data);
return (-1);
} }
int int
cmd_unbind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx) cmd_unbind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
{ {
struct cmd_unbind_key_data *data = self->data; struct args *args = self->args;
struct key_binding *bd;
int key;
if (data == NULL) if (args_has(args, 'a')) {
while (!RB_EMPTY(&key_bindings)) {
bd = RB_ROOT(&key_bindings);
key_bindings_remove(bd->key);
}
return (0); return (0);
if (data->tablename != NULL) }
return (cmd_unbind_key_table(self, ctx));
key_bindings_remove(data->key); key = key_string_lookup_string(args->argv[0]);
if (key == KEYC_NONE) {
ctx->error(ctx, "unknown key: %s", args->argv[0]);
return (-1);
}
if (args_has(args, 't'))
return (cmd_unbind_key_table(self, ctx, key));
if (!args_has(args, 'n'))
key |= KEYC_PREFIX;
key_bindings_remove(key);
return (0); return (0);
} }
int int
cmd_unbind_key_table(struct cmd *self, struct cmd_ctx *ctx) cmd_unbind_key_table(struct cmd *self, struct cmd_ctx *ctx, int key)
{ {
struct cmd_unbind_key_data *data = self->data; struct args *args = self->args;
const char *tablename;
const struct mode_key_table *mtab; const struct mode_key_table *mtab;
struct mode_key_binding *mbind, mtmp; struct mode_key_binding *mbind, mtmp;
if ((mtab = mode_key_findtable(data->tablename)) == NULL) { tablename = args_get(args, 't');
ctx->error(ctx, "unknown key table: %s", data->tablename); if ((mtab = mode_key_findtable(tablename)) == NULL) {
ctx->error(ctx, "unknown key table: %s", tablename);
return (-1); return (-1);
} }
mtmp.key = data->key & ~KEYC_PREFIX; mtmp.key = key;
mtmp.mode = data->command_key ? 1 : 0; mtmp.mode = !!args_has(args, 'c');
if ((mbind = SPLAY_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) { if ((mbind = RB_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) {
SPLAY_REMOVE(mode_key_tree, mtab->tree, mbind); RB_REMOVE(mode_key_tree, mtab->tree, mbind);
xfree(mbind); xfree(mbind);
} }
return (0); return (0);
} }
void
cmd_unbind_key_free(struct cmd *self)
{
struct cmd_unbind_key_data *data = self->data;
if (data->tablename != NULL)
xfree(data->tablename);
xfree(data);
}

View File

@@ -1,4 +1,4 @@
/* $Id: cmd-unlink-window.c,v 1.21 2009-12-04 22:14:47 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -28,26 +28,25 @@ int cmd_unlink_window_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_unlink_window_entry = { const struct cmd_entry cmd_unlink_window_entry = {
"unlink-window", "unlinkw", "unlink-window", "unlinkw",
"kt:", 0, 0,
"[-k] " CMD_TARGET_WINDOW_USAGE, "[-k] " CMD_TARGET_WINDOW_USAGE,
0, "k", 0,
cmd_target_init, NULL,
cmd_target_parse, NULL,
cmd_unlink_window_exec, cmd_unlink_window_exec
cmd_target_free,
cmd_target_print
}; };
int int
cmd_unlink_window_exec(struct cmd *self, struct cmd_ctx *ctx) cmd_unlink_window_exec(struct cmd *self, struct cmd_ctx *ctx)
{ {
struct cmd_target_data *data = self->data; struct args *args = self->args;
struct winlink *wl; struct winlink *wl;
struct window *w; struct window *w;
struct session *s, *s2; struct session *s, *s2;
struct session_group *sg; struct session_group *sg;
u_int references; u_int references;
if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) if ((wl = cmd_find_window(ctx, args_get(args, 't'), &s)) == NULL)
return (-1); return (-1);
w = wl->window; w = wl->window;
@@ -59,7 +58,7 @@ cmd_unlink_window_exec(struct cmd *self, struct cmd_ctx *ctx)
} else } else
references = 1; references = 1;
if (!cmd_check_flag(data->chflags, 'k') && w->references == references) { if (!args_has(self->args, 'k') && w->references == references) {
ctx->error(ctx, "window is only linked to one session"); ctx->error(ctx, "window is only linked to one session");
return (-1); return (-1);
} }

View File

@@ -1,60 +0,0 @@
/* $Id: cmd-up-pane.c,v 1.14 2010-01-05 23:52:37 tcunha Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
*
* 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 "tmux.h"
/*
* Move up a pane.
*/
int cmd_up_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_up_pane_entry = {
"up-pane", "upp",
CMD_TARGET_WINDOW_USAGE,
0, "",
cmd_target_init,
cmd_target_parse,
cmd_up_pane_exec,
cmd_target_free,
cmd_target_print
};
int
cmd_up_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
struct cmd_target_data *data = self->data;
struct winlink *wl;
struct window *w;
if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
return (-1);
w = wl->window;
do {
w->active = TAILQ_PREV(w->active, window_panes, entry);
if (w->active == NULL)
w->active = TAILQ_LAST(&w->panes, window_panes);
} while (!window_pane_visible(w->active));
server_status_window(wl->window);
server_redraw_window_borders(wl->window);
return (0);
}

483
cmd.c
View File

@@ -1,4 +1,4 @@
/* $Id: cmd.c,v 1.137 2010-01-22 17:28:34 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,6 +31,7 @@ const struct cmd_entry *cmd_table[] = {
&cmd_bind_key_entry, &cmd_bind_key_entry,
&cmd_break_pane_entry, &cmd_break_pane_entry,
&cmd_capture_pane_entry, &cmd_capture_pane_entry,
&cmd_choose_buffer_entry,
&cmd_choose_client_entry, &cmd_choose_client_entry,
&cmd_choose_session_entry, &cmd_choose_session_entry,
&cmd_choose_window_entry, &cmd_choose_window_entry,
@@ -38,13 +39,11 @@ const struct cmd_entry *cmd_table[] = {
&cmd_clock_mode_entry, &cmd_clock_mode_entry,
&cmd_command_prompt_entry, &cmd_command_prompt_entry,
&cmd_confirm_before_entry, &cmd_confirm_before_entry,
&cmd_copy_buffer_entry,
&cmd_copy_mode_entry, &cmd_copy_mode_entry,
&cmd_delete_buffer_entry, &cmd_delete_buffer_entry,
&cmd_detach_client_entry, &cmd_detach_client_entry,
&cmd_display_message_entry, &cmd_display_message_entry,
&cmd_display_panes_entry, &cmd_display_panes_entry,
&cmd_down_pane_entry,
&cmd_find_window_entry, &cmd_find_window_entry,
&cmd_has_session_entry, &cmd_has_session_entry,
&cmd_if_shell_entry, &cmd_if_shell_entry,
@@ -53,6 +52,7 @@ const struct cmd_entry *cmd_table[] = {
&cmd_kill_server_entry, &cmd_kill_server_entry,
&cmd_kill_session_entry, &cmd_kill_session_entry,
&cmd_kill_window_entry, &cmd_kill_window_entry,
&cmd_last_pane_entry,
&cmd_last_window_entry, &cmd_last_window_entry,
&cmd_link_window_entry, &cmd_link_window_entry,
&cmd_list_buffers_entry, &cmd_list_buffers_entry,
@@ -79,13 +79,13 @@ const struct cmd_entry *cmd_table[] = {
&cmd_rename_session_entry, &cmd_rename_session_entry,
&cmd_rename_window_entry, &cmd_rename_window_entry,
&cmd_resize_pane_entry, &cmd_resize_pane_entry,
&cmd_respawn_pane_entry,
&cmd_respawn_window_entry, &cmd_respawn_window_entry,
&cmd_rotate_window_entry, &cmd_rotate_window_entry,
&cmd_run_shell_entry, &cmd_run_shell_entry,
&cmd_save_buffer_entry, &cmd_save_buffer_entry,
&cmd_select_layout_entry, &cmd_select_layout_entry,
&cmd_select_pane_entry, &cmd_select_pane_entry,
&cmd_select_prompt_entry,
&cmd_select_window_entry, &cmd_select_window_entry,
&cmd_send_keys_entry, &cmd_send_keys_entry,
&cmd_send_prefix_entry, &cmd_send_prefix_entry,
@@ -108,16 +108,22 @@ const struct cmd_entry *cmd_table[] = {
&cmd_switch_client_entry, &cmd_switch_client_entry,
&cmd_unbind_key_entry, &cmd_unbind_key_entry,
&cmd_unlink_window_entry, &cmd_unlink_window_entry,
&cmd_up_pane_entry,
NULL NULL
}; };
struct session *cmd_choose_session(struct sessions *); struct session *cmd_choose_session_list(struct sessionslist *);
struct session *cmd_choose_session(int);
struct client *cmd_choose_client(struct clients *); struct client *cmd_choose_client(struct clients *);
struct client *cmd_lookup_client(const char *); struct client *cmd_lookup_client(const char *);
struct session *cmd_lookup_session(const char *, int *); struct session *cmd_lookup_session(const char *, int *);
struct winlink *cmd_lookup_window(struct session *, const char *, int *); struct winlink *cmd_lookup_window(struct session *, const char *, int *);
int cmd_lookup_index(struct session *, const char *, int *); int cmd_lookup_index(struct session *, const char *, int *);
struct window_pane *cmd_lookup_paneid(const char *);
struct session *cmd_pane_session(struct cmd_ctx *,
struct window_pane *, struct winlink **);
struct winlink *cmd_find_window_offset(const char *, struct session *, int *);
int cmd_find_index_offset(const char *, struct session *, int *);
struct window_pane *cmd_find_pane_offset(const char *, struct winlink *);
int int
cmd_pack_argv(int argc, char **argv, char *buf, size_t len) cmd_pack_argv(int argc, char **argv, char *buf, size_t len)
@@ -163,6 +169,22 @@ cmd_unpack_argv(char *buf, size_t len, int argc, char ***argv)
return (0); return (0);
} }
char **
cmd_copy_argv(int argc, char *const *argv)
{
char **new_argv;
int i;
if (argc == 0)
return (NULL);
new_argv = xcalloc(argc, sizeof *new_argv);
for (i = 0; i < argc; i++) {
if (argv[i] != NULL)
new_argv[i] = xstrdup(argv[i]);
}
return (new_argv);
}
void void
cmd_free_argv(int argc, char **argv) cmd_free_argv(int argc, char **argv)
{ {
@@ -182,8 +204,9 @@ cmd_parse(int argc, char **argv, char **cause)
{ {
const struct cmd_entry **entryp, *entry; const struct cmd_entry **entryp, *entry;
struct cmd *cmd; struct cmd *cmd;
struct args *args;
char s[BUFSIZ]; char s[BUFSIZ];
int opt, ambiguous = 0; int ambiguous = 0;
*cause = NULL; *cause = NULL;
if (argc == 0) { if (argc == 0) {
@@ -217,30 +240,19 @@ cmd_parse(int argc, char **argv, char **cause)
return (NULL); return (NULL);
} }
optreset = 1; args = args_parse(entry->args_template, argc, argv);
optind = 1; if (args == NULL)
if (entry->parse == NULL) { goto usage;
while ((opt = getopt(argc, argv, "")) != -1) { if (entry->args_lower != -1 && args->argc < entry->args_lower)
switch (opt) { goto usage;
default: if (entry->args_upper != -1 && args->argc > entry->args_upper)
goto usage; goto usage;
} if (entry->check != NULL && entry->check(args) != 0)
} goto usage;
argc -= optind;
argv += optind;
if (argc != 0)
goto usage;
}
cmd = xmalloc(sizeof *cmd); cmd = xmalloc(sizeof *cmd);
cmd->entry = entry; cmd->entry = entry;
cmd->data = NULL; cmd->args = args;
if (entry->parse != NULL) {
if (entry->parse(cmd, argc, argv, cause) != 0) {
xfree(cmd);
return (NULL);
}
}
return (cmd); return (cmd);
ambiguous: ambiguous:
@@ -258,6 +270,8 @@ ambiguous:
return (NULL); return (NULL);
usage: usage:
if (args != NULL)
args_free(args);
xasprintf(cause, "usage: %s %s", entry->name, entry->usage); xasprintf(cause, "usage: %s %s", entry->name, entry->usage);
return (NULL); return (NULL);
} }
@@ -271,17 +285,27 @@ cmd_exec(struct cmd *cmd, struct cmd_ctx *ctx)
void void
cmd_free(struct cmd *cmd) cmd_free(struct cmd *cmd)
{ {
if (cmd->data != NULL && cmd->entry->free != NULL) if (cmd->args != NULL)
cmd->entry->free(cmd); args_free(cmd->args);
xfree(cmd); xfree(cmd);
} }
size_t size_t
cmd_print(struct cmd *cmd, char *buf, size_t len) cmd_print(struct cmd *cmd, char *buf, size_t len)
{ {
if (cmd->entry->print == NULL) size_t off, used;
return (xsnprintf(buf, len, "%s", cmd->entry->name));
return (cmd->entry->print(cmd, buf, len)); off = xsnprintf(buf, len, "%s ", cmd->entry->name);
if (off < len) {
used = args_print(cmd->args, buf + off, len - off);
if (used == 0)
buf[off - 1] = '\0';
else {
off += used;
buf[off] = '\0';
}
}
return (off);
} }
/* /*
@@ -292,15 +316,14 @@ cmd_print(struct cmd *cmd, char *buf, size_t len)
* session from all sessions. * session from all sessions.
*/ */
struct session * struct session *
cmd_current_session(struct cmd_ctx *ctx) cmd_current_session(struct cmd_ctx *ctx, int prefer_unattached)
{ {
struct msg_command_data *data = ctx->msgdata; struct msg_command_data *data = ctx->msgdata;
struct client *c = ctx->cmdclient; struct client *c = ctx->cmdclient;
struct session *s; struct session *s;
struct sessions ss; struct sessionslist ss;
struct winlink *wl; struct winlink *wl;
struct window_pane *wp; struct window_pane *wp;
u_int i;
int found; int found;
if (ctx->curclient != NULL && ctx->curclient->session != NULL) if (ctx->curclient != NULL && ctx->curclient->session != NULL)
@@ -313,9 +336,7 @@ cmd_current_session(struct cmd_ctx *ctx)
*/ */
if (c != NULL && c->tty.path != NULL) { if (c != NULL && c->tty.path != NULL) {
ARRAY_INIT(&ss); ARRAY_INIT(&ss);
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { RB_FOREACH(s, sessions, &sessions) {
if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
continue;
found = 0; found = 0;
RB_FOREACH(wl, winlinks, &s->windows) { RB_FOREACH(wl, winlinks, &s->windows) {
TAILQ_FOREACH(wp, &wl->window->panes, entry) { TAILQ_FOREACH(wp, &wl->window->panes, entry) {
@@ -331,29 +352,49 @@ cmd_current_session(struct cmd_ctx *ctx)
ARRAY_ADD(&ss, s); ARRAY_ADD(&ss, s);
} }
s = cmd_choose_session(&ss); s = cmd_choose_session_list(&ss);
ARRAY_FREE(&ss); ARRAY_FREE(&ss);
if (s != NULL) if (s != NULL)
return (s); return (s);
} }
/* Use the session from the TMUX environment variable. */ /* Use the session from the TMUX environment variable. */
if (data != NULL && data->pid != -1) { if (data != NULL && data->pid == getpid() && data->idx != -1) {
if (data->pid != getpid()) s = session_find_by_index(data->idx);
return (NULL); if (s != NULL)
if (data->idx > ARRAY_LENGTH(&sessions)) return (s);
return (NULL);
if ((s = ARRAY_ITEM(&sessions, data->idx)) == NULL)
return (NULL);
return (s);
} }
return (cmd_choose_session(&sessions)); return (cmd_choose_session(prefer_unattached));
}
/*
* Find the most recently used session, preferring unattached if the flag is
* set.
*/
struct session *
cmd_choose_session(int prefer_unattached)
{
struct session *s, *sbest;
struct timeval *tv = NULL;
sbest = NULL;
RB_FOREACH(s, sessions, &sessions) {
if (tv == NULL || timercmp(&s->activity_time, tv, >) ||
(prefer_unattached &&
!(sbest->flags & SESSION_UNATTACHED) &&
(s->flags & SESSION_UNATTACHED))) {
sbest = s;
tv = &s->activity_time;
}
}
return (sbest);
} }
/* Find the most recently used session from a list. */ /* Find the most recently used session from a list. */
struct session * struct session *
cmd_choose_session(struct sessions *ss) cmd_choose_session_list(struct sessionslist *ss)
{ {
struct session *s, *sbest; struct session *s, *sbest;
struct timeval *tv = NULL; struct timeval *tv = NULL;
@@ -393,7 +434,7 @@ cmd_current_client(struct cmd_ctx *ctx)
* No current client set. Find the current session and return the * No current client set. Find the current session and return the
* newest of its clients. * newest of its clients.
*/ */
s = cmd_current_session(ctx); s = cmd_current_session(ctx, 0);
if (s != NULL && !(s->flags & SESSION_UNATTACHED)) { if (s != NULL && !(s->flags & SESSION_UNATTACHED)) {
ARRAY_INIT(&cc); ARRAY_INIT(&cc);
for (i = 0; i < ARRAY_LENGTH(&clients); i++) { for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
@@ -501,7 +542,6 @@ struct session *
cmd_lookup_session(const char *name, int *ambiguous) cmd_lookup_session(const char *name, int *ambiguous)
{ {
struct session *s, *sfound; struct session *s, *sfound;
u_int i;
*ambiguous = 0; *ambiguous = 0;
@@ -510,21 +550,15 @@ cmd_lookup_session(const char *name, int *ambiguous)
* be unique so an exact match can't be ambigious and can just be * be unique so an exact match can't be ambigious and can just be
* returned. * returned.
*/ */
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { if ((s = session_find(name)) != NULL)
if ((s = ARRAY_ITEM(&sessions, i)) == NULL) return (s);
continue;
if (strcmp(name, s->name) == 0)
return (s);
}
/* /*
* Otherwise look for partial matches, returning early if it is found to * Otherwise look for partial matches, returning early if it is found to
* be ambiguous. * be ambiguous.
*/ */
sfound = NULL; sfound = NULL;
for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { RB_FOREACH(s, sessions, &sessions) {
if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
continue;
if (strncmp(name, s->name, strlen(name)) == 0 || if (strncmp(name, s->name, strlen(name)) == 0 ||
fnmatch(name, s->name, 0) == 0) { fnmatch(name, s->name, 0) == 0) {
if (sfound != NULL) { if (sfound != NULL) {
@@ -540,7 +574,7 @@ cmd_lookup_session(const char *name, int *ambiguous)
/* /*
* Lookup a window or return -1 if not found or ambigious. First try as an * Lookup a window or return -1 if not found or ambigious. First try as an
* index and if invalid, use fnmatch or leading prefix. Return NULL but fill in * index and if invalid, use fnmatch or leading prefix. Return NULL but fill in
* idx if the window index is a valid number but there is now window with that * idx if the window index is a valid number but there is no window with that
* index. * index.
*/ */
struct winlink * struct winlink *
@@ -614,26 +648,89 @@ cmd_lookup_index(struct session *s, const char *name, int *ambiguous)
return (-1); return (-1);
} }
/*
* Lookup pane id. An initial % means a pane id. sp must already point to the
* current session.
*/
struct window_pane *
cmd_lookup_paneid(const char *arg)
{
const char *errstr;
u_int paneid;
if (*arg != '%')
return (NULL);
paneid = strtonum(arg + 1, 0, UINT_MAX, &errstr);
if (errstr != NULL)
return (NULL);
return (window_pane_find_by_id(paneid));
}
/* Find session and winlink for pane. */
struct session *
cmd_pane_session(struct cmd_ctx *ctx, struct window_pane *wp,
struct winlink **wlp)
{
struct session *s;
struct sessionslist ss;
struct winlink *wl;
/* If this pane is in the current session, return that winlink. */
s = cmd_current_session(ctx, 0);
if (s != NULL) {
wl = winlink_find_by_window(&s->windows, wp->window);
if (wl != NULL) {
if (wlp != NULL)
*wlp = wl;
return (s);
}
}
/* Otherwise choose from all sessions with this pane. */
ARRAY_INIT(&ss);
RB_FOREACH(s, sessions, &sessions) {
if (winlink_find_by_window(&s->windows, wp->window) != NULL)
ARRAY_ADD(&ss, s);
}
s = cmd_choose_session_list(&ss);
ARRAY_FREE(&ss);
if (wlp != NULL)
*wlp = winlink_find_by_window(&s->windows, wp->window);
return (s);
}
/* Find the target session or report an error and return NULL. */ /* Find the target session or report an error and return NULL. */
struct session * struct session *
cmd_find_session(struct cmd_ctx *ctx, const char *arg) cmd_find_session(struct cmd_ctx *ctx, const char *arg, int prefer_unattached)
{ {
struct session *s; struct session *s;
struct client *c; struct window_pane *wp;
char *tmparg; struct client *c;
size_t arglen; char *tmparg;
int ambiguous; size_t arglen;
int ambiguous;
/* A NULL argument means the current session. */ /* A NULL argument means the current session. */
if (arg == NULL) if (arg == NULL)
return (cmd_current_session(ctx)); return (cmd_current_session(ctx, prefer_unattached));
tmparg = xstrdup(arg);
/* Lookup as pane id. */
if ((wp = cmd_lookup_paneid(arg)) != NULL)
return (cmd_pane_session(ctx, wp, NULL));
/* Trim a single trailing colon if any. */ /* Trim a single trailing colon if any. */
tmparg = xstrdup(arg);
arglen = strlen(tmparg); arglen = strlen(tmparg);
if (arglen != 0 && tmparg[arglen - 1] == ':') if (arglen != 0 && tmparg[arglen - 1] == ':')
tmparg[arglen - 1] = '\0'; tmparg[arglen - 1] = '\0';
/* An empty session name is the current session. */
if (*tmparg == '\0') {
xfree(tmparg);
return (cmd_current_session(ctx, prefer_unattached));
}
/* Find the session, if any. */ /* Find the session, if any. */
s = cmd_lookup_session(tmparg, &ambiguous); s = cmd_lookup_session(tmparg, &ambiguous);
@@ -657,17 +754,18 @@ cmd_find_session(struct cmd_ctx *ctx, const char *arg)
struct winlink * struct winlink *
cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp) cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp)
{ {
struct session *s; struct session *s;
struct winlink *wl; struct winlink *wl;
const char *winptr; struct window_pane *wp;
char *sessptr = NULL; const char *winptr;
int ambiguous = 0; char *sessptr = NULL;
int ambiguous = 0;
/* /*
* Find the current session. There must always be a current session, if * Find the current session. There must always be a current session, if
* it can't be found, report an error. * it can't be found, report an error.
*/ */
if ((s = cmd_current_session(ctx)) == NULL) { if ((s = cmd_current_session(ctx, 0)) == NULL) {
ctx->error(ctx, "can't establish current session"); ctx->error(ctx, "can't establish current session");
return (NULL); return (NULL);
} }
@@ -679,6 +777,14 @@ cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp)
return (s->curw); return (s->curw);
} }
/* Lookup as pane id. */
if ((wp = cmd_lookup_paneid(arg)) != NULL) {
s = cmd_pane_session(ctx, wp, &wl);
if (sp != NULL)
*sp = s;
return (wl);
}
/* Time to look at the argument. If it is empty, that is an error. */ /* Time to look at the argument. If it is empty, that is an error. */
if (*arg == '\0') if (*arg == '\0')
goto not_found; goto not_found;
@@ -707,10 +813,8 @@ cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp)
wl = s->curw; wl = s->curw;
else if (winptr[0] == '!' && winptr[1] == '\0') else if (winptr[0] == '!' && winptr[1] == '\0')
wl = TAILQ_FIRST(&s->lastw); wl = TAILQ_FIRST(&s->lastw);
else if (winptr[0] == '+' && winptr[1] == '\0') else if (winptr[0] == '+' || winptr[0] == '-')
wl = winlink_next(s->curw); wl = cmd_find_window_offset(winptr, s, &ambiguous);
else if (winptr[0] == '-' && winptr[1] == '\0')
wl = winlink_previous(s->curw);
else else
wl = cmd_lookup_window(s, winptr, &ambiguous); wl = cmd_lookup_window(s, winptr, &ambiguous);
if (wl == NULL) if (wl == NULL)
@@ -728,25 +832,28 @@ no_colon:
if (arg[0] == '!' && arg[1] == '\0') { if (arg[0] == '!' && arg[1] == '\0') {
if ((wl = TAILQ_FIRST(&s->lastw)) == NULL) if ((wl = TAILQ_FIRST(&s->lastw)) == NULL)
goto not_found; goto not_found;
} else if (arg[0] == '+' && arg[1] == '\0') { } else if (arg[0] == '+' || arg[0] == '-') {
if ((wl = winlink_next(s->curw)) == NULL) if ((wl = cmd_find_window_offset(arg, s, &ambiguous)) == NULL)
goto not_found; goto lookup_session;
} else if (arg[0] == '-' && arg[1] == '\0') { } else if ((wl = cmd_lookup_window(s, arg, &ambiguous)) == NULL)
if ((wl = winlink_previous(s->curw)) == NULL) goto lookup_session;
goto not_found;
} else if ((wl = cmd_lookup_window(s, arg, &ambiguous)) == NULL) {
if (ambiguous)
goto not_found;
if ((s = cmd_lookup_session(arg, &ambiguous)) == NULL)
goto no_session;
wl = s->curw;
}
if (sp != NULL) if (sp != NULL)
*sp = s; *sp = s;
return (wl); return (wl);
lookup_session:
if (ambiguous)
goto not_found;
if (*arg != '\0' && (s = cmd_lookup_session(arg, &ambiguous)) == NULL)
goto no_session;
if (sp != NULL)
*sp = s;
return (s->curw);
no_session: no_session:
if (ambiguous) if (ambiguous)
ctx->error(ctx, "multiple sessions: %s", arg); ctx->error(ctx, "multiple sessions: %s", arg);
@@ -766,6 +873,26 @@ not_found:
return (NULL); return (NULL);
} }
struct winlink *
cmd_find_window_offset(const char *winptr, struct session *s, int *ambiguous)
{
struct winlink *wl;
int offset = 1;
if (winptr[1] != '\0')
offset = strtonum(winptr + 1, 1, INT_MAX, NULL);
if (offset == 0)
wl = cmd_lookup_window(s, winptr, ambiguous);
else {
if (winptr[0] == '+')
wl = winlink_next_by_number(s->curw, s, offset);
else
wl = winlink_previous_by_number(s->curw, s, offset);
}
return (wl);
}
/* /*
* Find the target session and window index, whether or not it exists in the * Find the target session and window index, whether or not it exists in the
* session. Return -2 on error or -1 if no window index is specified. This is * session. Return -2 on error or -1 if no window index is specified. This is
@@ -785,7 +912,7 @@ cmd_find_index(struct cmd_ctx *ctx, const char *arg, struct session **sp)
* Find the current session. There must always be a current session, if * Find the current session. There must always be a current session, if
* it can't be found, report an error. * it can't be found, report an error.
*/ */
if ((s = cmd_current_session(ctx)) == NULL) { if ((s = cmd_current_session(ctx, 0)) == NULL) {
ctx->error(ctx, "can't establish current session"); ctx->error(ctx, "can't establish current session");
return (-2); return (-2);
} }
@@ -827,20 +954,11 @@ cmd_find_index(struct cmd_ctx *ctx, const char *arg, struct session **sp)
if ((wl = TAILQ_FIRST(&s->lastw)) == NULL) if ((wl = TAILQ_FIRST(&s->lastw)) == NULL)
goto not_found; goto not_found;
idx = wl->idx; idx = wl->idx;
} else if (winptr[0] == '+' && winptr[1] == '\0') { } else if (winptr[0] == '+' || winptr[0] == '-') {
if (s->curw->idx == INT_MAX) if ((idx = cmd_find_index_offset(winptr, s, &ambiguous)) < 0)
goto not_found; goto invalid_index;
idx = s->curw->idx + 1; } else if ((idx = cmd_lookup_index(s, winptr, &ambiguous)) == -1)
} else if (winptr[0] == '-' && winptr[1] == '\0') { goto invalid_index;
if (s->curw->idx == 0)
goto not_found;
idx = s->curw->idx - 1;
} else if ((idx = cmd_lookup_index(s, winptr, &ambiguous)) == -1) {
if (ambiguous)
goto not_found;
ctx->error(ctx, "invalid index: %s", arg);
idx = -2;
}
if (sessptr != NULL) if (sessptr != NULL)
xfree(sessptr); xfree(sessptr);
@@ -855,27 +973,28 @@ no_colon:
if ((wl = TAILQ_FIRST(&s->lastw)) == NULL) if ((wl = TAILQ_FIRST(&s->lastw)) == NULL)
goto not_found; goto not_found;
idx = wl->idx; idx = wl->idx;
} else if (arg[0] == '+' && arg[1] == '\0') { } else if (arg[0] == '+' || arg[0] == '-') {
if (s->curw->idx == INT_MAX) if ((idx = cmd_find_index_offset(arg, s, &ambiguous)) < 0)
goto not_found; goto lookup_session;
idx = s->curw->idx + 1; } else if ((idx = cmd_lookup_index(s, arg, &ambiguous)) == -1)
} else if (arg[0] == '-' && arg[1] == '\0') { goto lookup_session;
if (s->curw->idx == 0)
goto not_found;
idx = s->curw->idx - 1;
} else if ((idx = cmd_lookup_index(s, arg, &ambiguous)) == -1) {
if (ambiguous)
goto not_found;
if ((s = cmd_lookup_session(arg, &ambiguous)) == NULL)
goto no_session;
idx = -1;
}
if (sp != NULL) if (sp != NULL)
*sp = s; *sp = s;
return (idx); return (idx);
lookup_session:
if (ambiguous)
goto not_found;
if (*arg != '\0' && (s = cmd_lookup_session(arg, &ambiguous)) == NULL)
goto no_session;
if (sp != NULL)
*sp = s;
return (-1);
no_session: no_session:
if (ambiguous) if (ambiguous)
ctx->error(ctx, "multiple sessions: %s", arg); ctx->error(ctx, "multiple sessions: %s", arg);
@@ -885,6 +1004,15 @@ no_session:
xfree(sessptr); xfree(sessptr);
return (-2); return (-2);
invalid_index:
if (ambiguous)
goto not_found;
ctx->error(ctx, "invalid index: %s", arg);
if (sessptr != NULL)
xfree(sessptr);
return (-2);
not_found: not_found:
if (ambiguous) if (ambiguous)
ctx->error(ctx, "multiple windows: %s", arg); ctx->error(ctx, "multiple windows: %s", arg);
@@ -895,6 +1023,32 @@ not_found:
return (-2); return (-2);
} }
int
cmd_find_index_offset(const char *winptr, struct session *s, int *ambiguous)
{
int idx, offset = 1;
if (winptr[1] != '\0')
offset = strtonum(winptr + 1, 1, INT_MAX, NULL);
if (offset == 0)
idx = cmd_lookup_index(s, winptr, ambiguous);
else {
if (winptr[0] == '+') {
if (s->curw->idx == INT_MAX)
idx = cmd_lookup_index(s, winptr, ambiguous);
else
idx = s->curw->idx + offset;
} else {
if (s->curw->idx == 0)
idx = cmd_lookup_index(s, winptr, ambiguous);
else
idx = s->curw->idx - offset;
}
}
return (idx);
}
/* /*
* Find the target session, window and pane number or report an error and * Find the target session, window and pane number or report an error and
* return NULL. The pane number is separated from the session:window by a ., * return NULL. The pane number is separated from the session:window by a .,
@@ -904,15 +1058,14 @@ struct winlink *
cmd_find_pane(struct cmd_ctx *ctx, cmd_find_pane(struct cmd_ctx *ctx,
const char *arg, struct session **sp, struct window_pane **wpp) const char *arg, struct session **sp, struct window_pane **wpp)
{ {
struct session *s; struct session *s;
struct winlink *wl; struct winlink *wl;
struct layout_cell *lc; const char *period, *errstr;
const char *period, *errstr; char *winptr, *paneptr;
char *winptr, *paneptr; u_int idx;
u_int idx;
/* Get the current session. */ /* Get the current session. */
if ((s = cmd_current_session(ctx)) == NULL) { if ((s = cmd_current_session(ctx, 0)) == NULL) {
ctx->error(ctx, "can't establish current session"); ctx->error(ctx, "can't establish current session");
return (NULL); return (NULL);
} }
@@ -925,6 +1078,14 @@ cmd_find_pane(struct cmd_ctx *ctx,
return (s->curw); return (s->curw);
} }
/* Lookup as pane id. */
if ((*wpp = cmd_lookup_paneid(arg)) != NULL) {
s = cmd_pane_session(ctx, *wpp, &wl);
if (sp != NULL)
*sp = s;
return (wl);
}
/* Look for a separating period. */ /* Look for a separating period. */
if ((period = strrchr(arg, '.')) == NULL) if ((period = strrchr(arg, '.')) == NULL)
goto no_period; goto no_period;
@@ -941,6 +1102,8 @@ cmd_find_pane(struct cmd_ctx *ctx,
paneptr = winptr + (period - arg) + 1; paneptr = winptr + (period - arg) + 1;
if (*paneptr == '\0') if (*paneptr == '\0')
*wpp = wl->window->active; *wpp = wl->window->active;
else if (paneptr[0] == '+' || paneptr[0] == '-')
*wpp = cmd_find_pane_offset(paneptr, wl);
else { else {
idx = strtonum(paneptr, 0, INT_MAX, &errstr); idx = strtonum(paneptr, 0, INT_MAX, &errstr);
if (errstr != NULL) if (errstr != NULL)
@@ -955,14 +1118,13 @@ cmd_find_pane(struct cmd_ctx *ctx,
lookup_string: lookup_string:
/* Try pane string description. */ /* Try pane string description. */
if ((lc = layout_find_string(s->curw->window, paneptr)) == NULL) { if ((*wpp = window_find_string(wl->window, paneptr)) == NULL) {
ctx->error(ctx, "can't find pane: %s", paneptr); ctx->error(ctx, "can't find pane: %s", paneptr);
goto error; goto error;
} }
*wpp = lc->wp;
xfree(winptr); xfree(winptr);
return (s->curw); return (wl);
no_period: no_period:
/* Try as a pane number alone. */ /* Try as a pane number alone. */
@@ -978,10 +1140,8 @@ no_period:
lookup_window: lookup_window:
/* Try pane string description. */ /* Try pane string description. */
if ((lc = layout_find_string(s->curw->window, arg)) != NULL) { if ((*wpp = window_find_string(s->curw->window, arg)) != NULL)
*wpp = lc->wp;
return (s->curw); return (s->curw);
}
/* Try as a window and use the active pane. */ /* Try as a window and use the active pane. */
if ((wl = cmd_find_window(ctx, arg, sp)) != NULL) if ((wl = cmd_find_window(ctx, arg, sp)) != NULL)
@@ -993,6 +1153,25 @@ error:
return (NULL); return (NULL);
} }
struct window_pane *
cmd_find_pane_offset(const char *paneptr, struct winlink *wl)
{
struct window *w = wl->window;
struct window_pane *wp = w->active;
u_int offset = 1;
if (paneptr[1] != '\0')
offset = strtonum(paneptr + 1, 1, INT_MAX, NULL);
if (offset > 0) {
if (paneptr[0] == '+')
wp = window_pane_next_by_number(w, wp, offset);
else
wp = window_pane_previous_by_number(w, wp, offset);
}
return (wp);
}
/* Replace the first %% or %idx in template by s. */ /* Replace the first %% or %idx in template by s. */
char * char *
cmd_template_replace(char *template, const char *s, int idx) cmd_template_replace(char *template, const char *s, int idx)
@@ -1033,3 +1212,35 @@ cmd_template_replace(char *template, const char *s, int idx)
return (buf); return (buf);
} }
/* Return the default path for a new pane. */
const char *
cmd_get_default_path(struct cmd_ctx *ctx)
{
const char *cwd;
struct session *s;
struct window_pane *wp;
struct environ_entry *envent;
if ((s = cmd_current_session(ctx, 0)) == NULL)
return (NULL);
cwd = options_get_string(&s->options, "default-path");
if ((cwd[0] == '~' && cwd[1] == '\0') || !strcmp(cwd, "$HOME")) {
envent = environ_find(&global_environ, "HOME");
if (envent != NULL && *envent->value != '\0')
return envent->value;
cwd = "";
}
if (*cwd == '\0') {
if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL)
return (ctx->cmdclient->cwd);
if (ctx->curclient != NULL) {
wp = s->curw->window->active;
if ((cwd = osdep_get_cwd(wp->pid)) != NULL)
return (cwd);
}
return (s->cwd);
}
return (cwd);
}

159
colour.c
View File

@@ -1,4 +1,4 @@
/* $Id: colour.c,v 1.7 2009-09-11 14:13:52 tcunha Exp $ */ /* $Id$ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -18,6 +18,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <ctype.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -28,6 +29,100 @@
* of the 256 colour palette. * of the 256 colour palette.
*/ */
/* An RGB colour. */
struct colour_rgb {
u_char r;
u_char g;
u_char b;
};
/* 256 colour RGB table, generated on first use. */
struct colour_rgb *colour_rgb_256;
void colour_rgb_generate256(void);
u_int colour_rgb_distance(struct colour_rgb *, struct colour_rgb *);
int colour_rgb_find(struct colour_rgb *);
/* Generate 256 colour RGB table. */
void
colour_rgb_generate256(void)
{
struct colour_rgb *rgb;
u_int i, r, g, b;
/*
* Allocate the table. The first 16 colours are often changed by users
* and terminals so don't include them.
*/
colour_rgb_256 = xcalloc(240, sizeof *colour_rgb_256);
/* Add the colours first. */
r = g = b = 0;
for (i = 240; i > 24; i--) {
rgb = &colour_rgb_256[240 - i];
if (r != 0)
rgb->r = (r * 40) + 55;
if (g != 0)
rgb->g = (g * 40) + 55;
if (b != 0)
rgb->b = (b * 40) + 55;
b++;
if (b > 5) {
b = 0;
g++;
}
if (g > 5) {
g = 0;
r++;
}
}
/* Then add the greys. */
for (i = 24; i > 0; i--) {
rgb = &colour_rgb_256[240 - i];
rgb->r = 8 + (24 - i) * 10;
rgb->g = 8 + (24 - i) * 10;
rgb->b = 8 + (24 - i) * 10;
}
}
/* Get colour RGB distance. */
u_int
colour_rgb_distance(struct colour_rgb *rgb1, struct colour_rgb *rgb2)
{
int r, g, b;
r = rgb1->r - rgb2->r;
g = rgb1->g - rgb2->g;
b = rgb1->b - rgb2->b;
return (r * r + g * g + b * b);
}
/* Work out the nearest colour from the 256 colour set. */
int
colour_rgb_find(struct colour_rgb *rgb)
{
u_int distance, lowest, colour, i;
if (colour_rgb_256 == NULL)
colour_rgb_generate256();
colour = 16;
lowest = UINT_MAX;
for (i = 0; i < 240; i++) {
distance = colour_rgb_distance(&colour_rgb_256[i], rgb);
if (distance < lowest) {
lowest = distance;
colour = 16 + i;
}
}
return (colour);
}
/* Set grid cell foreground colour. */
void void
colour_set_fg(struct grid_cell *gc, int c) colour_set_fg(struct grid_cell *gc, int c)
{ {
@@ -36,6 +131,7 @@ colour_set_fg(struct grid_cell *gc, int c)
gc->fg = c; gc->fg = c;
} }
/* Set grid cell background colour. */
void void
colour_set_bg(struct grid_cell *gc, int c) colour_set_bg(struct grid_cell *gc, int c)
{ {
@@ -44,6 +140,7 @@ colour_set_bg(struct grid_cell *gc, int c)
gc->bg = c; gc->bg = c;
} }
/* Convert colour to a string. */
const char * const char *
colour_tostring(int c) colour_tostring(int c)
{ {
@@ -73,15 +170,45 @@ colour_tostring(int c)
return ("white"); return ("white");
case 8: case 8:
return ("default"); return ("default");
case 90:
return ("brightblack");
case 91:
return ("brightred");
case 92:
return ("brightgreen");
case 93:
return ("brightyellow");
case 94:
return ("brightblue");
case 95:
return ("brightmagenta");
case 96:
return ("brightcyan");
case 97:
return ("brightwhite");
} }
return (NULL); return (NULL);
} }
/* Convert colour from string. */
int int
colour_fromstring(const char *s) colour_fromstring(const char *s)
{ {
const char *errstr; const char *errstr;
int n; const char *cp;
struct colour_rgb rgb;
int n;
if (*s == '#' && strlen(s) == 7) {
for (cp = s + 1; isxdigit((u_char) *cp); cp++)
;
if (*cp != '\0')
return (-1);
n = sscanf(s + 1, "%2hhx%2hhx%2hhx", &rgb.r, &rgb.g, &rgb.b);
if (n != 3)
return (-1);
return (colour_rgb_find(&rgb) | 0x100);
}
if (strncasecmp(s, "colour", (sizeof "colour") - 1) == 0) { if (strncasecmp(s, "colour", (sizeof "colour") - 1) == 0) {
n = strtonum(s + (sizeof "colour") - 1, 0, 255, &errstr); n = strtonum(s + (sizeof "colour") - 1, 0, 255, &errstr);
@@ -108,9 +235,34 @@ colour_fromstring(const char *s)
return (7); return (7);
if (strcasecmp(s, "default") == 0 || (s[0] == '8' && s[1] == '\0')) if (strcasecmp(s, "default") == 0 || (s[0] == '8' && s[1] == '\0'))
return (8); return (8);
if (strcasecmp(s, "brightblack") == 0 ||
(s[0] == '9' && s[1] == '0' && s[1] == '\0'))
return (90);
if (strcasecmp(s, "brightred") == 0 ||
(s[0] == '9' && s[1] == '1' && s[1] == '\0'))
return (91);
if (strcasecmp(s, "brightgreen") == 0 ||
(s[0] == '9' && s[1] == '2' && s[1] == '\0'))
return (92);
if (strcasecmp(s, "brightyellow") == 0 ||
(s[0] == '9' && s[1] == '3' && s[1] == '\0'))
return (93);
if (strcasecmp(s, "brightblue") == 0 ||
(s[0] == '9' && s[1] == '4' && s[1] == '\0'))
return (94);
if (strcasecmp(s, "brightmagenta") == 0 ||
(s[0] == '9' && s[1] == '5' && s[1] == '\0'))
return (95);
if (strcasecmp(s, "brightcyan") == 0 ||
(s[0] == '9' && s[1] == '6' && s[1] == '\0'))
return (96);
if (strcasecmp(s, "brightwhite") == 0 ||
(s[0] == '9' && s[1] == '7' && s[1] == '\0'))
return (97);
return (-1); return (-1);
} }
/* Convert 256 colour palette to 16. */
u_char u_char
colour_256to16(u_char c) colour_256to16(u_char c)
{ {
@@ -136,6 +288,7 @@ colour_256to16(u_char c)
return (table[c]); return (table[c]);
} }
/* Convert 256 colour palette to 88. */
u_char u_char
colour_256to88(u_char c) colour_256to88(u_char c)
{ {

Some files were not shown because too many files have changed in this diff Show More