Merge with latest tmux

This commit is contained in:
Nicolas Viennot 2015-12-23 05:41:41 -05:00
commit 9b2778c439
222 changed files with 22308 additions and 13427 deletions

2
.gitignore vendored
View File

@ -6,6 +6,7 @@
core
tags
.deps/
compat/.dirstamp
aclocal.m4
autom4te.cache/
config.log
@ -19,3 +20,4 @@ tmate
cscope.*
ctags
*.log
tmate.1.*

View File

@ -1,24 +1,36 @@
Bob Beck <beck@openbsd.org> beck <beck>
Igor Sobrado <sobrado@openbsd.org> sobrado <sobrado>
Jacek Masiulaniec <jacekm@openbsd.org> jacekm <jacekm>
Jason McIntyre <jmc@openbsd.org> jcm <jcm>
Bob Beck <beck@openbsd.org> beck <beck>
Claudio Jeker <claudio@openbsd.org> claudio <claudio>
Igor Sobrado <sobrado@openbsd.org> sobrado <sobrado>
Ingo Schwarze <schwarze@openbsd.org> schwarze <schwarze>
Jacek Masiulaniec <jacekm@openbsd.org> jacekm <jacekm>
Jason McIntyre <jmc@openbsd.org> jmc <jmc>
Joel Sing <jsing@openbsd.org> jsing <jsing>
Marc Espie <espie@openbsd.org> espie <espie>
Matthew Dempsky <matthew@openbsd.org> matthew <matthew>
Matthias Kilian <kili@openbsd.org> kili <kili>
Matthieu Herrb <matthieu@openbsd.org> matthieu <matthieu>
Miod Vallat <miod@openbsd.org> miod <miod>
Nicholas Marriott <nicm@openbsd.org> nicm <nicm>
Nicholas Marriott <nicm@openbsd.org> no_author <no_author@example.org>
<nicm@openbsd.org> <nicholas.marriott@gmail.com>
Okan Demirmen <okan@openbsd.org> okan <okan>
Jonathan Gray <jsg@openbsd.org> jsg <jsg>
Kenneth R Westerback <krw@openbsd.org> krw <krw>
Marc Espie <espie@openbsd.org> espie <espie>
Matthew Dempsky <matthew@openbsd.org> matthew <matthew>
Matthias Kilian <kili@openbsd.org> kili <kili>
Matthieu Herrb <matthieu@openbsd.org> matthieu <matthieu>
Michael McConville <mmcc@openbsd.org> mmcc <mmcc>
Miod Vallat <miod@openbsd.org> miod <miod>
Nicholas Marriott <nicholas.marriott@gmail.com> Nicholas Marriott <nicm@openbsd.org>
Nicholas Marriott <nicholas.marriott@gmail.com> nicm <nicm>
Nicholas Marriott <nicholas.marriott@gmail.com> no_author <no_author@example.org>
Okan Demirmen <okan@openbsd.org> okan <okan>
Philip Guenther <guenther@openbsd.org> guenther <guenther>
Pierre-Yves Ritschard <pyr@openbsd.org> pyr <pyr>
Ray Lai <ray@openbsd.org> ray <ray>
Pierre-Yves Ritschard <pyr@openbsd.org> pyr <pyr>
Ray Lai <ray@openbsd.org> ray <ray>
Ryan McBride <mcbride@openbsd.org> mcbride <mcbride>
Stefan Sperling <stsp@openbsd.org> stsp <stsp>
Stuart Henderson <sthen@openbsd.org> sthen <sthen>
Ted Unangst <tedu@openbsd.org> tedu <tedu>
Theo Deraadt <deraadt@openbsd.org> deraadt <deraadt>
Sebastian Benoit <benno@openbsd.org> benno <benno>
Stefan Sperling <stsp@openbsd.org> stsp <stsp>
Stuart Henderson <sthen@openbsd.org> sthen <sthen>
Ted Unangst <tedu@openbsd.org> tedu <tedu>
Theo de Raadt <deraadt@openbsd.org> Theo Deraadt <deraadt@openbsd.org>
Theo de Raadt <deraadt@openbsd.org> deraadt <deraadt>
Thomas Adam <thomas@xteddy.org> Thomas <thomas@xteddy.org>
William Yodlowsky <william@openbsd.org> william <william>
Thomas Adam <thomas@xteddy.org> Thomas Adam <thomas.adam@smoothwall.net>
Thomas Adam <thomas@xteddy.org> n6tadam <n6tadam@xteddy.org>
Tim van der Molen <tim@openbsd.org> tim <tim>
Tobias Stoeckmann <tobias@openbsd.org> tobias <tobias>
Todd C Miller <millert@openbsd.org> millert <millert>
William Yodlowsky <william@openbsd.org> william <william>

10
.travis.yml Normal file
View File

@ -0,0 +1,10 @@
language: c
matrix:
include:
- compiler: gcc
- compiler: clang
env: CFLAGS="-g -O2"
before_install:
- sudo apt-get update -qq
- sudo apt-get -y install debhelper autotools-dev dh-autoreconf file libncurses5-dev libevent-dev pkg-config libutempter-dev build-essential
script: (CFLAGS= ./autogen.sh) && ./configure --enable-debug && make

189
CHANGES
View File

@ -1,3 +1,179 @@
CHANGES FROM 2.0 to 2.1 18 October 2015
Incompatible Changes
====================
* Mouse-mode has been rewritten. There's now no longer options for:
- mouse-resize-pane
- mouse-select-pane
- mouse-select-window
- mode-mouse
Instead there is just one option: 'mouse' which turns on mouse support
entirely.
* 'default-terminal' is now a session option. Furthermore, if this is set
to 'screen-*' then emulate what screen does. If italics are wanted, this
can be set to 'tmux' but this is still new and not necessarily supported
on all platforms with older ncurses installs.
* The c0-* options for rate-limiting have been removed. Instead, a backoff
approach is used.
Normal Changes
==============
* New formats:
- session_activity
- window_linked
- window_activity_format
- session_alerts
- session_last_attached
- client_pid
- pid
* 'copy-selection', 'append-selection', 'start-named-buffer' now understand
an '-x' flag to prevent it exiting copying mode.
* 'select-pane' now understands '-P' to set window/pane background colours.
* 'renumber-windows' now understands windows which are unlinked.
* 'bind' now understands multiple key tables. Allows for key-chaining.
* 'select-layout' understands '-o' to undo the last layout change.
* The environment is updated when switching sessions as well as attaching.
* 'select-pane' now understands '-M' for marking a pane. This marked pane
can then be used with commands which understand src-pane specifiers
automatically.
* If a session/window target is prefixed with '=' then only an exact match
is considered.
* 'move-window' understands '-a'.
* 'update-environment' understands '-E' when attach-session is used on an
already attached client.
* 'show-environment' understands '-s' to output Bourne-compatible commands.
* New option: 'history-file' to save/restore command prompt history.
* Copy mode is exited if the history is cleared whilst in copy-mode.
* 'copy-mode' learned '-e' to exit copy-mode when scrolling to end.
CHANGES FROM 1.9a to 2.0 6 March 2015
Incompatible Changes
====================
* The choose-list command has been removed.
* 'terminal-overrides' is now a server option, not a session option.
* 'message-limit' is now a server option, not a session option.
* 'monitor-content' option has been removed.
* 'pane_start_path' option has been removed.
* The "info" mechanism which used to (for some commands) provide feedback
has been removed, and like other commands, they now produce nothing on
success.
Normal Changes
==============
* tmux can now write an entry to utmp if the library 'utempter' is present
at compile time.
* set-buffer learned append mode (-a), and a corresponding
'append-selection' command has been added to copy-mode.
* choose-mode now has the following commands which can be bound:
- start-of-list
- end-of-list
- top-line
- bottom-line
* choose-buffer now understands UTF-8.
* Pane navigation has changed:
- The old way of always using the top or left if the choice is ambiguous.
- The new way of remembering the last used pane is annoying if the
layout is balanced and the leftmost is obvious to the user (because
clearly if we go right from the top-left in a tiled set of four we want
to end up in top-right, even if we were last using the bottom-right).
So instead, use a combination of both: if there is only one possible
pane alongside the current pane, move to it, otherwise choose the most
recently used of the choice.
* 'set-buffer' can now be told to give names to buffers.
* The 'new-session', 'new-window', 'split-window', and 'respawn-pane' commands
now understand multiple arguments and handle quoting problems correctly.
* 'capture-pane' understands '-S-' to mean the start of the pane, and '-E-' to
mean the end of the pane.
* Support for function keys beyond F12 has changed. The following explains:
- F13-F24 are S-F1 to S-F12
- F25-F36 are C-F1 to C-F12
- F37-F48 are C-S-F1 to C-S-F12
- F49-F60 are M-F1 to M-F12
- F61-F63 are M-S-F1 to M-S-F3
Therefore, F13 becomes a binding of S-F1, etc.
* Support using pane id as part of session or window specifier (so % means
session-of-%1 or window-of-%1) and window id as part of session
(so @1 means session-of-@1).
* 'copy-pipe' command now understands formats via -F
* 'if-shell' command now understands formats via -F
* 'split-window' and 'join-window' understand -b to create the pane to the left
or above the target pane.
CHANGES FROM 1.9 to 1.9a 22 February 2014
NOTE: This is a bug-fix release to address some important bugs which just
missed the 1.9 deadline, but were found afterwards.
Normal Changes
==============
* Fix crash due to uninitialized lastwp member of layout_cell
* Fix -fg/-bg/-style with 256 colour terminals.
CHANGES FROM 1.8 to 1.9, 20 February 2014
NOTE: This release has bumped the tmux protocol version. It is therefore
advised that the prior tmux server is restarted when this version of tmux is
installed, to avoid protocol mismatch errors for newer clients trying to
talk to an older running tmux server.
Incompatible Changes
====================
* 88 colour support has been removed.
* 'default-path' has been removed. The new-window command accepts '-c' to
cater for this. The previous value of "." can be replaced with: 'neww -c
$PWD', the previous value of '' which meant current path of the pane can
be specified as: 'neww -c "#{pane_current_path}"'
Deprecated Changes
==================
* The single format specifiers: #A -> #Z (where defined) have been
deprecated and replaced with longer-named equivalents, as listed in the
FORMATS section of the tmux manpage.
* The various foo-{fg,bg,attr} commands have been deprecated and replaced
with equivalent foo-style option instead. Currently this is still
backwards-compatible, but will be removed over time.
Normal Changes
==============
* A new environment variable TMUX_TMPDIR is now honoured, allowing the
socket directory to be set outside of TMPDIR (/tmp/ if not set).
* If -s not given to swap-pane the current pane is assumed.
* A #{pane_syncronized} format specifier has been added to be a conditional
format if a pane is in a syncronised mode (c.f. syncronize-panes)
* Tmux now runs under Cygwin natively.
* Formats can now be nested within each other and expanded accordingly.
* Added 'automatic-rename-format' option to allow the automatic rename
mechanism to use something other than the default of
#{pane_current_command}.
* new-session learnt '-c' to specify the starting directory for that session
and all subsequent windows therein.
* The session name is now shown in the message printed to the terminal when
a session is detached.
* Lots more format specifiers have been added.
* Server race conditions have been fixed; in particular commands are not run
until after the configuration file is read completely.
* Case insensitive searching in tmux's copy-mode is now possible.
* attach-session and switch-client learnt the '-t' option to accept a window
and/or a pane to use.
* Copy-mode is only exited if no selection is in progress.
* Paste key in copy-mode is now possible to enter text from the clipboard.
* status-interval set to '0' now works as intended.
* tmux now supports 256 colours running under fbterm.
* Many bug fixes!
CHANGES FROM 1.7 to 1.8, 26 March 2013
Incompatible Changes
@ -17,7 +193,7 @@ Normal Changes
* run-shell learnt '-t' to specify the pane to use when displaying output.
* Support for middle-click pasting.
* choose-tree learns '-u' to start uncollapsed.
* select-window learnt '-T; to toggle to the last window if it's already
* select-window learnt '-T' to toggle to the last window if it's already
current.
* New session option 'assume-paste-time' for pasting text versus key-binding
actions.
@ -37,9 +213,9 @@ Normal Changes
the 'source-file' command.
* 'copy-pipe' mode command to copy selection and pipe the selection to a
command.
* Changes panes can now emit focus notifications for certain applications
* Panes can now emit focus notifications for certain applications
which use those.
* run-shell and if-shell now accept format placeholders.
* run-shell and if-shell now accept formats.
* resize-pane learnt '-Z' for zooming a pane temporarily.
* new-session learnt '-A' to make it behave like attach-session.
* set-option learnt '-o' to prevent setting an option which is already set.
@ -1799,10 +1975,3 @@ The list of older changes is below.
emacs) that don't require scrolling regions (ESC[r) mostly work fine
(including mutt, emacs). No status bar yet and no key remapping or other
customisation.
$Id$
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: dstidx srcname srcidx winlink lsw nabc sabc Exp Tiago Cunha dch
LocalWords: setw Chisnall renamew merdely eg Maier newname selectw neww Gass

21
COPYING Normal file
View File

@ -0,0 +1,21 @@
THIS IS FOR INFORMATION ONLY, CODE IS UNDER THE LICENCE AT THE TOP OF ITS FILE.
The README, CHANGES, FAQ and TODO files are licensed under the ISC
license. Files under examples/ remain copyright their authors unless otherwise
stated in the file but permission has been received to distribute them with
tmux. All other files have a license and copyright notice at their start,
typically:
Copyright (c) <author>
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.

130
FAQ
View File

@ -95,9 +95,6 @@ aware of are (bearing in mind I haven't used screen for a few years now):
- 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
@ -107,8 +104,12 @@ aware of are (bearing in mind I haven't used screen for a few years now):
* I found a bug! What do I do?
Please send bug reports by email to nicm@users.sourceforge.net or
tmux-users@lists.sourceforge.net. Please include as much of the following
Check the latest version of tmux from Git to see if the problem is still
reproducible. Sometimes the length of time between releases means a lot of
fixes can be sitting in Git and the problem might already be fixed.
Please send bug reports by email to nicholas.marriott@gmail.com or
tmux-users@googlegroups.com. Please include as much of the following
information as possible:
- the version of tmux you are running;
@ -122,7 +123,7 @@ information as possible:
* Why doesn't tmux do $x?
Please send feature requests by email to nicm@users.sourceforge.net.
Please send feature requests by email to tmux-users@googlegroups.com.
* Why do you use the screen terminal description inside tmux? It sucks.
@ -238,6 +239,31 @@ would be welcome.
vim users may also want to set the "ttyfast" option inside tmux.
* How do I make ctrl and shift arrow keys work in emacs?
The terminal-init-screen function in term/screen.el is called for new frames,
but it doesn't configure any function keys.
If the tmux xterm-keys option is on, it is enough to define the same keys as
xterm. Add the following to init.el or .emacs to do this:
(defadvice terminal-init-screen
;; The advice is named `tmux', and is run before `terminal-init-screen' runs.
(before tmux activate)
;; Docstring. This describes the advice and is made available inside emacs;
;; for example when doing C-h f terminal-init-screen RET
"Apply xterm keymap, allowing use of keys passed through tmux."
;; This is the elisp code that is run before `terminal-init-screen'.
(if (getenv "TMUX")
(let ((map (copy-keymap xterm-function-map)))
(set-keymap-parent map (keymap-parent input-decode-map))
(set-keymap-parent input-decode-map map))))
And ensure .tmux.conf contains "set -g xterm-keys on".
Alternatively, the screen.el file can be copied to the load path and
customized.
* 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
@ -326,42 +352,33 @@ 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'
* vim displays reverse video instead of italics, while less displays italics
(or just regular text) instead of reverse. What's wrong?
* I don't see italics! Or less and vim show italics and reverse the wrong way round!
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:
GNU screen does not support italics and the "screen" terminfo description uses
the italics escape sequence incorrectly.
$ 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
As of tmux 2.1, if default-terminal is set to "screen" or matches "screen-*",
tmux will behave like screen and italics will be disabled.
To enable italics, create a new terminfo entry called "tmux" (some platforms
may already have this, you can check with "infocmp tmux"):
$ cat <<EOF|tic -x -
tmux|tmux terminal multiplexer,
ritm=\E[23m, rmso=\E[27m, sitm=\E[3m, smso=\E[7m, Ms@,
use=xterm+tmux, use=screen,
tmux-256color|tmux with 256 colors,
use=xterm+256setaf, use=tmux,
EOF
$
And tell tmux to use it in ~/.tmux.conf:
set -g default-terminal "screen-it"
set -g default-terminal "tmux"
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:
If using urxvt, make sure you have an italics capable font enabled. for
example, add to ~/.Xdefaults:
urxvt.italicFont: xft:Bitstream Vera Sans Mono:italic:autohint=true
@ -377,7 +394,7 @@ always (or ever) be added to the scrollback.
You can make tmux use the normal screen by telling it that your terminal does
not have an alternate screen. Put the following in ~/.tmux.conf:
set -g terminal-overrides 'xterm*:smcup@:rmcup@'
set -ga terminal-overrides ',xterm*:smcup@:rmcup@'
Adjust if your $TERM does not start with xterm.
@ -396,5 +413,42 @@ configuration file:
Or the default window options:
$ tmux -Lfoo -f/dev/null start\; show -gw
* How do I copy a selection from tmux to the system's clipboard?
When running in xterm(1), tmux can automatically send copied text to the
clipboard. This is controlled by the set-clipboard option and also needs this
X resource to be set:
XTerm*disallowedWindowOps: 20,21,SetXprop
For rxvt-unicode (urxvt), there is an unofficial Perl extension here:
http://anti.teamidiot.de/static/nei/*/Code/urxvt/
Otherwise a key binding for copy mode using xclip (or xsel) works:
bind -temacs-copy C-y copy-pipe "xclip -i >/dev/null"
Or for inside and outside copy mode with the prefix key:
bind C-y run -b "tmux save-buffer - | xclip -i"
On OS X, reattach-to-usernamespace lets pbcopy/pbpaste work:
https://github.com/ChrisJohnsen/tmux-MacOSX-pasteboard
$Id$
* Why do I see dots around a session when I attach to it?
tmux limits the size of the window to the smallest attached session. If
it didn't do this then it would be impossible to see the entire window.
The dots mark the size of the window tmux can display.
To avoid this, detach all other clients when attaching:
$ tmux attach -d
Or from inside tmux by detaching individual clients with C-b D or all
using:
C-b : attach -d

View File

@ -1,19 +1,19 @@
# $Id$
# Makefile.am
# Obvious program stuff.
bin_PROGRAMS = tmate
dist_man1_MANS = tmate.1
CLEANFILES = tmate.1.mdoc tmate.1.man
# Distribution tarball options.
EXTRA_DIST = \
CHANGES FAQ README TODO examples compat \
array.h compat.h tmux.h osdep-*.c
CHANGES FAQ README TODO COPYING examples compat/*.[ch] \
array.h compat.h tmux.h tmate.h osdep-*.c mdoc2man.awk tmate.1
dist-hook:
make clean
grep "^#found_debug=" configure
find $(distdir) -name .svn -type d|xargs rm -Rf
# Preprocessor flags.
CPPFLAGS += @XOPEN_DEFINES@
CPPFLAGS += @XOPEN_DEFINES@ -DTMUX_CONF="\"$(sysconfdir)/tmux.conf\""
# glibc as usual does things ass-backwards and hides useful things by default,
# so everyone has to add this.
@ -21,79 +21,79 @@ if IS_GLIBC
CFLAGS += -D_GNU_SOURCE
endif
CFLAGS += -Wno-unused-parameter -Wno-unused-variable
# Set flags for gcc. gcc4 whines abouts silly stuff so it needs slightly
# different flags.
if IS_GCC
if IS_LINUX
CFLAGS += -rdynamic # for stack traces
CFLAGS += -std=gnu99
endif
# Set flags for gcc.
if IS_GCC
CFLAGS += -std=gnu99 -O2
if IS_DEBUG
CFLAGS += -O0 -g
CFLAGS += -g
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 += -Wbad-function-cast -Winline -Wcast-align
CFLAGS += -Wundef -Wbad-function-cast -Winline -Wcast-align
CFLAGS += -Wdeclaration-after-statement -Wno-pointer-sign -Wno-attributes
CPPFLAGS += -DDEBUG
else
CFLAGS += -O2
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
if IS_COVERAGE
CFLAGS += -g -O0 --coverage
LDFLAGS += --coverage
endif
CPPFLAGS += -iquote.
endif
# Set flags for Solaris.
if IS_SUNOS
if IS_GCC
CPPFLAGS += -D_XPG6 -D__EXTENSIONS__ -D_POSIX_PTHREAD_SEMANTICS
else
CPPFLAGS += -D_XPG4_2 -D__EXTENSIONS__ -D_POSIX_PTHREAD_SEMANTICS
endif
endif
# Set flags for Sun CC.
if IS_SUNCC
CFLAGS += -erroff=E_EMPTY_DECLARATION
endif
# Set _LINUX_SOURCE_COMPAT for AIX for mallocing 0 bytes
if IS_AIX
DEFS += -D_LINUX_SOURCE_COMPAT=1
endif
# List of sources.
dist_tmate_SOURCES = \
alerts.c \
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-list.c \
cmd-choose-tree.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.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 \
@ -120,23 +120,20 @@ dist_tmate_SOURCES = \
cmd-select-pane.c \
cmd-select-window.c \
cmd-send-keys.c \
cmd-server-info.c \
cmd-set-buffer.c \
cmd-set-environment.c \
cmd-set-hook.c \
cmd-set-option.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-wait-for.c \
cmd.c \
colour.c \
@ -144,9 +141,9 @@ dist_tmate_SOURCES = \
control-notify.c \
environ.c \
format.c \
grid-cell.c \
grid-view.c \
grid.c \
hooks.c \
input-keys.c \
input.c \
job.c \
@ -162,17 +159,18 @@ dist_tmate_SOURCES = \
options-table.c \
options.c \
paste.c \
proc.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 \
style.c \
tmate-debug.c \
tmate-ssh-client.c \
tmate-encoder.c \
@ -222,6 +220,9 @@ endif
if NO_FGETLN
nodist_tmate_SOURCES += compat/fgetln.c
endif
if NO_FPARSELN
nodist_tmate_SOURCES += compat/fparseln.c
endif
if NO_GETOPT
nodist_tmate_SOURCES += compat/getopt.c
endif
@ -240,3 +241,25 @@ endif
if NO_B64_NTOP
nodist_tmate_SOURCES += compat/b64_ntop.c
endif
if NO_CFMAKERAW
nodist_tmate_SOURCES += compat/cfmakeraw.c
endif
if NO_OPENAT
nodist_tmate_SOURCES += compat/openat.c
endif
if NO_REALLOCARRAY
nodist_tmate_SOURCES += compat/reallocarray.c
endif
# Install tmate.1 in the right format.
install-exec-hook:
if test x@MANFORMAT@ = xmdoc; then \
sed -e "s|@SYSCONFDIR@|$(sysconfdir)|g" $(srcdir)/tmate.1 \
>$(srcdir)/tmate.1.mdoc; \
else \
sed -e "s|@SYSCONFDIR@|$(sysconfdir)|g" $(srcdir)/tmate.1| \
$(AWK) -f$(srcdir)/mdoc2man.awk >$(srcdir)/tmate.1.man; \
fi
$(mkdir_p) $(DESTDIR)$(mandir)/man1
$(INSTALL_DATA) $(srcdir)/tmate.1.@MANFORMAT@ \
$(DESTDIR)$(mandir)/man1/tmate.1

View File

@ -4,10 +4,9 @@ tmux is a "terminal multiplexer", it enables a number of terminals (or windows)
to be accessed and controlled from a single terminal. tmux is intended to be a
simple, modern, BSD-licensed alternative to programs such as GNU screen.
This release runs on OpenBSD, FreeBSD, NetBSD, Linux and OS X and may still
run on Solaris and AIX (although they haven't been tested in a while).
This release runs on OpenBSD, FreeBSD, NetBSD, Linux, OS X and Solaris.
Since the 1.2 release tmux depends on libevent. Download it from:
tmux depends on libevent 2.x. Download it from:
http://www.monkey.org/~provos/libevent/
@ -18,14 +17,13 @@ To build tmux from a release tarball, do:
To get and build the latest from version control:
$ git clone git://git.code.sf.net/p/tmux/tmux-code tmux
$ git clone https://github.com/tmux/tmux.git
$ cd tmux
$ sh autogen.sh
$ ./configure && make
For more information see https://sourceforge.net/scm/?type=git&group_id=200378
and http://git-scm.com. Patches should be sent by email to the mailing list at
tmux-users@lists.sourceforge.net.
For more information see http://git-scm.com. Patches should be sent by email to
the mailing list at tmux-users@googlegroups.com.
For documentation on using tmux, see the tmux.1 manpage. It can be viewed from
the source tree with:
@ -41,20 +39,23 @@ directory.
For debugging, running tmux with -v or -vv will generate server and client log
files in the current directory.
tmux mailing lists are available. Visit:
tmux mailing lists are available. For general discussion and bug reports:
https://sourceforge.net/mail/?group_id=200378
https://groups.google.com/forum/#!forum/tmux-users
And for Git commit emails:
https://groups.google.com/forum/#!forum/tmux-git
Bug reports, feature suggestions and especially code contributions are most
welcome. Please send by email to:
tmux-users@lists.sourceforge.net
tmux-users@googlegroups.com
This file and the CHANGES, FAQ and TODO files are licensed under the ISC
license. Files under examples/ remain copyright their authors unless otherwise
stated in the file but permission has been received to distribute them with
tmux. All other files have a license and copyright notice at their start.
This file and the CHANGES, FAQ, SYNCING and TODO files are licensed under
the ISC license. Files under examples/ remain copyright their authors unless
otherwise stated in the file but permission has been received to distribute
them with tmux. All other files have a license and copyright notice at their
start.
-- Nicholas Marriott <nicm@users.sf.net>
$Id$
-- Nicholas Marriott <nicholas.marriott@gmail.com>

View File

@ -9,25 +9,4 @@ Tmate is a fork of tmux. It provides an instant pairing solution.
License
-------
tmate is built on top of tmux, libssh and msgpack. Their respective licenses are
in the sources. tmate is MIT licensed.
Copyright (c) 2013 Nicolas Viennot
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
tmate is built on top of tmux. tmux and tmate are BSD-licensed.

82
SYNCING
View File

@ -1,10 +1,10 @@
Preamble
========
Tmux on SourceForge has two git repositories [1] "tmux-code" and "tmux-openbsd".
Tmux portable relies on repositories "tmux" and "tmux-openbsd".
Here's a description of them:
* "tmux-code" is the portable version, the one which contains code for other
* "tmux" is the portable version, the one which contains code for other
operating systems, and autotools, etc., which isn't found or needed in the
OpenBSD base system.
@ -17,9 +17,6 @@ repository will take at least that long to appear in this git repository.
(It might take longer, depending on the CVS mirror used to import the
OpenBSD code).
It is assumed that the person doing the sync has read/write access to the
tmux-code repository on SourceForge already.
If you've never used git before, git tracks meta-data about the committer
and the author, as part of a commit, hence:
@ -37,11 +34,11 @@ this information has ever been set before.
Cloning repositories
====================
This involves having both tmux-code and tmux-openbsd cloned, as in:
This involves having both tmux and tmux-openbsd cloned, as in:
% cd /some/where/useful
% git clone ssh://${USER}@git.code.sf.net/p/tmux/tmux
% git clone ssh://${USER}@git.code.sf.net/p/tmux/tmux-openbsd
% git clone https://github.com/tmux/tmux.git
% git clone https://github.com/ThomasAdam/tmux-openbsd.git
Note that you do not need additional checkouts to manage the sync -- an
existing clone of either repositories will suffice. So if you already have
@ -50,56 +47,56 @@ these checkouts existing, skip that.
Adding in git-remotes
=====================
Because the portable "tmux-code" git repository and the "tmux-openbsd"
Because the portable "tmux" git repository and the "tmux-openbsd"
repository do not inherently share any history between each other, the
history has been faked between them. This "faking of history" is something
which has to be told to git for the purposes of comparing the "tmux" and
"tmux-openbsd" repositories for syncing. To do this, we must reference the
clone of the "tmux-openbsd" repository from the "tmux-code" repository, as
clone of the "tmux-openbsd" repository from the "tmux" repository, as
shown by the following command:
% cd /path/to/tmux-code
% cd /path/to/tmux
% git remote add obsd-tmux file:///path/to/tmux-openbsd
So that now, the remote "obsd-tmux" can be used to reference branches and
commits from the "tmux-openbsd" repository, but from the context of the
portable "tmux-code" repository, which makes sense because it's the "tmux"
portable "tmux" repository, which makes sense because it's the "tmux"
repository which will have the updates applied to them.
Fetching updates
================
To ensure the latest commits from "tmux-openbsd" can be found from within
"tmux-code", we have to ensure the "master" branch from "tmux-openbsd" is
up-to-date first, and then reference that update in "tmux-code", as in:
"tmux", we have to ensure the "master" branch from "tmux-openbsd" is
up-to-date first, and then reference that update in "tmux", as in:
% cd /path/to/tmux-openbsd
% git checkout master
% git pull
Then back in "tmux-code":
Then back in "tmux":
% cd /path/to/tmux-code
% git fetch obsd-tmux-code
% cd /path/to/tmux
% git fetch obsd-tmux
Creating the necessary branches
===============================
Now that "tmux-code" can see commits and branches from "tmux-openbsd" by way
Now that "tmux" can see commits and branches from "tmux-openbsd" by way
of the remote name "obsd-tmux", we can now create the master branch from
"tmux-openbsd" in the "tmux-code" repository:
"tmux-openbsd" in the "tmux" repository:
% git checkout -b obsd-master obsd-tmux/master
Adding in the fake history points
=================================
To tie both the "master" branch from "tmux-code" and the "obsd-master"
To tie both the "master" branch from "tmux" and the "obsd-master"
branch from "tmux-openbsd" together, the fake history points added to the
"tmux-code" repository need to be added. To do this, we must add an
"tmux" repository need to be added. To do this, we must add an
additional refspec line, as in:
% cd /path/to/tmux-code
% cd /path/to/tmux
% git config --add remote.origin.fetch '+refs/replace/*:refs/replace/*'
% git fetch origin
@ -110,7 +107,7 @@ Make sure the "master" branch is checked out:
% git checkout master
The following will show commits on OpenBSD not yet synched with "tmux-code":
The following will show commits on OpenBSD not yet synched with "tmux":
% git log master..obsd-master
@ -131,6 +128,15 @@ And if happy:
% git push origin master
Keeping an eye on libutil in OpenBSD
====================================
A lot of the compat/ code in tmux comes from libutil, especially imsg.
Sometimes the API can change, etc., which might cause interesting problems
trying to run the portable version of tmux. It's worth checking
periodically for any changes to libutil in OpenBSD and syncing those files
to compat/ as and when appropriate.
Release tmux for next version
=============================
@ -145,30 +151,26 @@ Release tmux for next version
3. Tag with:
% git tag -a 1.X
% git tag -a 2.X
Where "1.X" is the next version.
Where "2.X" is the next version.
Push the tag out with:
% git push 1.X
% git push 2.X
4. Build the tarball with make dist. Now that it's using autoconf there
shouldn't be any weird files (such as the original and rejection files
from patch(1)) but it doesn't hurt taking a quick look at it.
4. Build the tarball with 'make dist'.
5. Split the release changes into a new file. This should be named
tmux-$VERSION-readme to make sourceforge show it automagically in specific
parts of the project page.
5. Check the tarball. If it's good, go here to select the tag just pushed:
6. Upload the tarball and the above file. Make the tarball the default
download by selecting all operating systems under the file details.
https://github.com/tmux/tmux/tags
7. Run make update-index.html upload-index.html to replace %%VERSION%%.
Click the "Add release notes", upload the tarball and add a link in the
description field to the CHANGES file.
8. Bump version in configure.ac and uncomment "found_debug=yes" to create
a debug build by default.
7. Clone the tmux.github.io repository, and change the RELEASE version in
the Makefile. Commit it, and run 'make' to replace %%VERSION%%. Push
the result out.
9. Update freshmeat.
[1] https://sourceforge.net/p/tmux/_list/git
8. Bump version in tmu/tmux.git configure.ac and uncomment "found_debug=yes" to
create a debug build by default.

274
TODO
View File

@ -1,155 +1,135 @@
NOTES
=====
- command bits and pieces:
* allow multiple targets: fnmatch for -t/-c, for example detach all
clients with -t*
* add -c for new-session like new-window
* ' and " should be parsed the same (eg "\e" vs '\e') in config
and command prompt
* last-pane across sessions
* list-keys should quote output so that bindings can just be used in
config file as-is
This file describes rough notes regarding ideas for potential future tmux
development. It's not necessarily guaranteed that items in this TODO file
will ever get implemented.
- make command sequences more usable
* don't require space after ;
* options for error handling: && and ||?
It is asked therefore, that anyone thinking of undertaking a task in this
TODO file, email tmux-users@lists.sf.net to discuss the feature.
- options bits and pieces:
* set-remain-on-exit is a complete hack
* way to set socket path from config file
Thie file is split up between tmux user interface (UI) issues, and terminal
compatibility issues.
- format improvements:
* option to quote format (#{q:session_name})
* formats need conditions for >0 (for #P)
* some way to pad # stuff with spaces
* formats to show if a window is linked into multiple sessions, into
multiple attached sessions, and is the active window in multiple
attached sessions?
TMUX UI ISSUES
==============
- choose mode improvements:
* choose-pane command (augment choose-tree to do this?)
* choose-mode and copy-mode are very similar, make choose-mode a subset?
* flag to choose-* for sort order
* choose mode would be better per client than per window?
* two choices (first one then second, for swap-pane and join-pane)
* choose modes should ditch the key bindings and just have fixed keys, and
be more customized to their purpose (d to delete a buffer for choose-buffer,
a preview of buffer contents, etc)
- improve monitor-*:
* straighten out rules for multiple clients
* think about what happens across sessions
* monitor changes within a region
* perhaps monitor /all/ panes in the window not just one
- improve mouse support:
* bind commands to mouse in different areas?
* commands executed when clicking on a pattern (URL)
- hooks!
- implicitly add exec to the commands for new windows (switch to disable it)?
- bring back detach-session to detach all clients on a session?
- 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
in $x time
- flags to centre screen in window
- activity/bell should be per-window not per-link? what if it is cur win in
session not being watched?
- 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
- 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?
- would be nice to be able to use "--" to mark start of command w/ neww etc
to avoid quoting
- make command sequences more usable: don't require space after ;, handle
errors better
- choice and more mode would be better per client than per window?
- hooks to which commands may be attached, for example: tmux add-hook
"new-session" if-shell "[ -e $HOME/.tmux-session.conf ]" source-file
$HOME/.tmux-session.conf
- way to set socket path from config file
- warts on current naming:
- display-time but message-fg/bg/attr
- list-* vs show-*
- server-info
- up-pane/down-pane/swap-pane -U/swap-pane -D vs next-*/previous-*
- split-window -> split-pane??
- 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)
-- idea of a "view" onto a window, need base x/y offsets for redraw
- commands should be able to succeed or fail and have || or && for command
lists
- some way to keep a command running continually and just use its last line of
output
- UTF-8 to a non-UTF-8 terminal should not be able to balls up
the terminal - www/ruby-addressable; make regress
- support esc-esc to quit in modes
- fix ctrl+F1-F4 output. to what?
- better utf8 support: window names, prompt input, message display
- option to move copy mode indicator into status line
- selection behaviour closer to vi in vi mode
- live update: server started with -U connects to server, requests sessions and
windows, receives fds
- sort out inheriting config from shell on new sessions/windows:
should pick up default-path/termios/etc from client if possible,
else leave empty/default
- link panes into multiple windows
- bells should be passed between sessions with visual-bell etc
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
flag for readonly)
- multiline status line (no?)
- support title stack, both internally and externally
http://docs.freebsd.org/cgi/getmsg.cgi?fetch=1149299+0+archive/2010/freebsd-questions/20100207.freebsd-questions
- 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. why?
- 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
- 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)
- 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
- incremental searching in copy mode.
- 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)
- pass shell commands as argv rather than strings, allow them to be specified
in commands without quotes
- named buffers and allow gaps in the stack
- 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
- wait-for command 20130222153957.GY6782@yelena.nicm.ath.cx
- last-pane across sessions
- 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 conditions for >0 (for #P)
- fetch full command line on !Linux, and add option to strip prefixes
such as "sh " "/bin/sh " etc etc
- synchronize-windows option
- append to buffer in copy mode
- way to paste w/o trailing whitespace
- flag to switch-client to switch all clients
- history of layouts and undo/redo flags to selectl
- way to tag a layout as a number/name
- optimize pane redraws, 20120318184853.GK10965@yelena.nicm.ath.cx
- support multibyte key strings
- allow commands to be executed when certain patterns in a screen
are clicked on with the mouse
- flag to make next/previous commands skip a window
- way to do tmux command/run-shell from mode keys
- send command to all windows
- choose-pane command (augment choose-tree to do this?)
- choose-mode and copy-mode are very similar. Perhaps make choose-mode a subset
of copy-mode in that it inherits key-bindings and other traits but not all
- add -c for new-session like new-window
- flag to choose-* for sort order (eg sort windows/sessions/clients by last
used time) - perhaps using formats (but what about numeric sort)?
- instead of separate window and session options, just one master options list
with each option having a type (window or session), then options on window,
on session, and global. for window options we look window->session->global,
and for session we look session->global
- maybe keep last layout + size around and if size reverts just put it back
- way to set hints/limits about pane size for resizing
- revamp layouts: they are too complicated, should be more closely integrated,
should support hints, layout sets should just be a special case of custom
layouts, and we should support panes that are not attached to a cell at
all. this could be the time to introduce panelink to replace layout_cell
- run-shell/if-shell should support formats
- attach should take a pane and select it as well as attaching
- attach should have a flag to create session if it doesn't exist. or better
new a flag to attach it
* display-time but message-fg/bg/attr
* list-* vs show-*
* split-window -> split-pane?
TERMINAL ISSUES
================
- better UTF-8 support:
* message display
* prompt input
* searching in copy mode
- use a better termcap internally instead of screen, perhaps xterm
- clear window title on exit (see using xterm title stack)
- get it passing all the vttest tests that don't require resizing the terminal
- support for bce
- use screen-256color when started on 256 colour terminal?
* 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!
- copy/paste improvements:
* incremental searching
* paste w/o trailing whitespace
* command to toggle selection not to move it in copy-mode
* regex searching
* copy-pipe should have -x as well
- layout stuff
* way to tag a layout as a number/name
* maybe keep last layout + size around and if size reverts just put it
back
* revamp layouts: they are too complicated, should be more closely
integrated, should support hints, layout sets should just be a
special case of custom layouts, and we should support panes that are
not attached to a cell at all. this could be the time to introduce
panelink to replace layout_cell
* way to set hints/limits about pane size for resizing
* panning over window (window larger than visible)
* a mode where one application can cross two panes (ie x|y, width =
COLUMNS/2 but height = ROWS * 2)
* general key to space cells out evenly (horiz or vert) within their
parent cell (could replace even-vert/even-horiz layouts)
* separate active panes for different clients
- terminfo bits
* use a better termcap internally instead of screen, perhaps xterm
* use screen-256color when started on 256 colour terminal?
- code cleanup
* instead of separate window and session options, just one master
options list with each option having a type (window or session), then
options on window, on session, and global. for window options we look
window->session->global, and for session we look session->global
* the way pane, window, session destroy is handled is too complicated
and the distinction between session.c, window.c and server-fn.c
functions is not clear. could we just have kill_pane(),
kill_window(), unlink_window(), kill_session() that fix up all data
structures (flagging sessions as dead) and return a value to say
whether clients need to be checked for dead sessions? sort of like
session_detach now but more so. or some other scheme to make it
simpler and clearer? also would be nice to remove/rename server-fn.c
* more readable way to work out the various things commands need to
know about the client, notably:
- is this the config file? (cmdq->c == NULL)
- is this a command client? (cmdq->c != NULL &&
cmdq->c->session == NULL)
- is this a control client?
- can i do stdin or stdout to this client?
or even guarantee that cmdq->c != NULL and provide a better way to
tell when in the config file - then we use cmdq->c if we need a
client w/o a session else cmd_current_client
* optimize pane redraws, 20120318184853.GK10965@yelena.nicm.ath.cx
- miscellaneous
* way to keep a job running just read its last line of output for #()
* link panes into multiple windows
* live update: server started with -U connects to server, requests
sessions and windows, receives file descriptors
* there are inconsistencies in what we get from old shell and what
comes from config for new sessions and windows. likewise, panes and
jobs and run-shell and lock command all start with slightly different
environments
* multiline status line?
* customizable command aliases
* automatic pane logging
* BCE? We are halfway there (output side is done for pane backgrounds),
just need to change how screen/grid handles erase
* copy mode key bindings should just be a standard key table, using
something like "copy-mode start-selection"; it could use
command-prompt for search, goto, etc:
bind -Temacs command-prompt -p'Search Up: ' 'copy-mode search-up %%'
it'd need a separate lookup, because modes are per-pane, perhaps a
table() cb to give the table name ("vi" or "emacs"). anything in the
table fires the command, anything not in the table is injected as a
key

277
alerts.c Normal file
View File

@ -0,0 +1,277 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2015 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 <event.h>
#include "tmux.h"
int alerts_fired;
void alerts_timer(int, short, void *);
int alerts_enabled(struct window *, int);
void alerts_callback(int, short, void *);
void alerts_reset(struct window *);
int alerts_check_all(struct session *, struct winlink *);
int alerts_check_bell(struct session *, struct winlink *);
int alerts_check_activity(struct session *, struct winlink *);
int alerts_check_silence(struct session *, struct winlink *);
void alerts_ring_bell(struct session *);
void
alerts_timer(__unused int fd, __unused short events, void *arg)
{
struct window *w = arg;
log_debug("@%u alerts timer expired", w->id);
alerts_reset(w);
alerts_queue(w, WINDOW_SILENCE);
}
void
alerts_callback(__unused int fd, __unused short events, __unused void *arg)
{
struct window *w;
struct session *s;
struct winlink *wl;
int flags, alerts;
RB_FOREACH(w, windows, &windows) {
RB_FOREACH(s, sessions, &sessions) {
if (s->flags & SESSION_UNATTACHED)
continue;
RB_FOREACH(wl, winlinks, &s->windows) {
if (wl->window != w)
continue;
flags = w->flags;
alerts = alerts_check_all(s, wl);
log_debug("%s:%d @%u alerts check, alerts %#x, "
"flags %#x", s->name, wl->idx, w->id,
alerts, flags);
}
}
}
alerts_fired = 0;
}
int
alerts_check_all(struct session *s, struct winlink *wl)
{
int alerts;
alerts = alerts_check_bell(s, wl);
alerts |= alerts_check_activity(s, wl);
alerts |= alerts_check_silence(s, wl);
if (alerts != 0)
server_status_session(s);
return (alerts);
}
void
alerts_check_session(struct session *s)
{
struct winlink *wl;
RB_FOREACH(wl, winlinks, &s->windows)
alerts_check_all(s, wl);
}
int
alerts_enabled(struct window *w, int flags)
{
if (flags & WINDOW_BELL)
return (1);
if (flags & WINDOW_ACTIVITY) {
if (options_get_number(w->options, "monitor-activity"))
return (1);
}
if (flags & WINDOW_SILENCE) {
if (options_get_number(w->options, "monitor-silence") != 0)
return (1);
}
return (0);
}
void
alerts_reset_all(void)
{
struct window *w;
RB_FOREACH(w, windows, &windows)
alerts_reset(w);
}
void
alerts_reset(struct window *w)
{
struct timeval tv;
w->flags &= ~WINDOW_SILENCE;
event_del(&w->alerts_timer);
timerclear(&tv);
tv.tv_sec = options_get_number(w->options, "monitor-silence");
log_debug("@%u alerts timer reset %u", w->id, (u_int)tv.tv_sec);
if (tv.tv_sec != 0)
event_add(&w->alerts_timer, &tv);
}
void
alerts_queue(struct window *w, int flags)
{
if (w->flags & WINDOW_ACTIVITY)
alerts_reset(w);
if (!event_initialized(&w->alerts_timer))
evtimer_set(&w->alerts_timer, alerts_timer, w);
if (!alerts_fired) {
w->flags |= flags;
log_debug("@%u alerts flags added %#x", w->id, flags);
if (alerts_enabled(w, flags)) {
log_debug("alerts check queued (by @%u)", w->id);
event_once(-1, EV_TIMEOUT, alerts_callback, NULL, NULL);
alerts_fired = 1;
}
}
}
int
alerts_check_bell(struct session *s, struct winlink *wl)
{
struct client *c;
struct window *w = wl->window;
int action, visual;
if (!(w->flags & WINDOW_BELL))
return (0);
if (s->curw != wl) {
wl->flags |= WINLINK_BELL;
w->flags &= ~WINDOW_BELL;
}
if (s->curw->window == w)
w->flags &= ~WINDOW_BELL;
action = options_get_number(s->options, "bell-action");
if (action == BELL_NONE)
return (0);
visual = options_get_number(s->options, "visual-bell");
TAILQ_FOREACH(c, &clients, entry) {
if (c->session != s || c->flags & CLIENT_CONTROL)
continue;
if (!visual) {
if ((action == BELL_CURRENT &&
c->session->curw->window == w) ||
(action == BELL_OTHER &&
c->session->curw->window != w) ||
action == BELL_ANY)
tty_putcode(&c->tty, TTYC_BEL);
continue;
}
if (action == BELL_CURRENT && c->session->curw->window == w)
status_message_set(c, "Bell in current window");
else if (action == BELL_ANY || (action == BELL_OTHER &&
c->session->curw->window != w))
status_message_set(c, "Bell in window %d", wl->idx);
}
return (WINDOW_BELL);
}
int
alerts_check_activity(struct session *s, struct winlink *wl)
{
struct client *c;
struct window *w = wl->window;
if (s->curw->window == w)
w->flags &= ~WINDOW_ACTIVITY;
if (!(w->flags & WINDOW_ACTIVITY) || wl->flags & WINLINK_ACTIVITY)
return (0);
if (s->curw == wl)
return (0);
if (!options_get_number(w->options, "monitor-activity"))
return (0);
if (options_get_number(s->options, "bell-on-alert"))
alerts_ring_bell(s);
wl->flags |= WINLINK_ACTIVITY;
if (options_get_number(s->options, "visual-activity")) {
TAILQ_FOREACH(c, &clients, entry) {
if (c->session != s)
continue;
status_message_set(c, "Activity in window %d", wl->idx);
}
}
return (WINDOW_ACTIVITY);
}
int
alerts_check_silence(struct session *s, struct winlink *wl)
{
struct client *c;
struct window *w = wl->window;
if (s->curw->window == w)
w->flags &= ~WINDOW_SILENCE;
if (!(w->flags & WINDOW_SILENCE) || wl->flags & WINLINK_SILENCE)
return (0);
if (s->curw == wl)
return (0);
if (options_get_number(w->options, "monitor-silence") == 0)
return (0);
if (options_get_number(s->options, "bell-on-alert"))
alerts_ring_bell(s);
wl->flags |= WINLINK_SILENCE;
if (options_get_number(s->options, "visual-silence")) {
TAILQ_FOREACH(c, &clients, entry) {
if (c->session != s)
continue;
status_message_set(c, "Silence in window %d", wl->idx);
}
}
return (WINDOW_SILENCE);
}
void
alerts_ring_bell(struct session *s)
{
struct client *c;
TAILQ_FOREACH(c, &clients, entry) {
if (c->session == s && !(c->flags & CLIENT_CONTROL))
tty_putcode(&c->tty, TTYC_BEL);
}
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net>
@ -20,9 +20,31 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h"
/*
* Manipulate command arguments.
*/
struct args_entry {
u_char flag;
char *value;
RB_ENTRY(args_entry) entry;
};
struct args_entry *args_find(struct args *, u_char);
RB_GENERATE(args_tree, args_entry, entry, args_cmp);
/* Arguments tree comparison function. */
int
args_cmp(struct args_entry *a1, struct args_entry *a2)
{
return (a1->flag - a2->flag);
}
/* Create an arguments set with no flags. */
struct args *
args_create(int argc, ...)
@ -32,8 +54,6 @@ args_create(int argc, ...)
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)
@ -49,35 +69,36 @@ args_create(int argc, ...)
return (args);
}
/* Find a flag in the arguments tree. */
struct args_entry *
args_find(struct args *args, u_char ch)
{
struct args_entry entry;
entry.flag = ch;
return (RB_FIND(args_tree, &args->tree, &entry));
}
/* 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)
if (opt < 0)
continue;
if (opt == '?' || (ptr = strchr(template, opt)) == NULL) {
free(args->flags);
free(args);
if (opt == '?' || strchr(template, opt) == NULL) {
args_free(args);
return (NULL);
}
bit_set(args->flags, opt);
if (ptr[1] == ':') {
free(args->values[opt]);
args->values[opt] = xstrdup(optarg);
}
args_set(args, opt, optarg);
}
argc -= optind;
argv += optind;
@ -92,122 +113,142 @@ args_parse(const char *template, int argc, char **argv)
void
args_free(struct args *args)
{
u_int i;
struct args_entry *entry;
struct args_entry *entry1;
cmd_free_argv(args->argc, args->argv);
for (i = 0; i < SCHAR_MAX; i++)
free(args->values[i]);
RB_FOREACH_SAFE(entry, args_tree, &args->tree, entry1) {
RB_REMOVE(args_tree, &args->tree, entry);
free(entry->value);
free(entry);
}
free(args->flags);
free(args);
}
/* Print a set of arguments. */
size_t
args_print(struct args *args, char *buf, size_t len)
/* Add to string. */
static void printflike(3, 4)
args_print_add(char **buf, size_t *len, const char *fmt, ...)
{
size_t off;
int i;
const char *quotes;
va_list ap;
char *s;
size_t slen;
/* There must be at least one byte at the start. */
if (len == 0)
return (0);
off = 0;
va_start(ap, fmt);
slen = xvasprintf(&s, fmt, ap);
va_end(ap);
*len += slen;
*buf = xrealloc(*buf, *len);
strlcat(*buf, s, *len);
free(s);
}
/* Print a set of arguments. */
char *
args_print(struct args *args)
{
size_t len;
char *buf;
int i;
struct args_entry *entry;
len = 1;
buf = xcalloc(1, len);
/* Process the flags first. */
buf[off++] = '-';
for (i = 0; i < SCHAR_MAX; i++) {
if (!bit_test(args->flags, i) || args->values[i] != NULL)
RB_FOREACH(entry, args_tree, &args->tree) {
if (entry->value != NULL)
continue;
if (off == len - 1) {
buf[off] = '\0';
return (len);
}
buf[off++] = i;
buf[off] = '\0';
if (*buf == '\0')
args_print_add(&buf, &len, "-");
args_print_add(&buf, &len, "%c", entry->flag);
}
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)
RB_FOREACH(entry, args_tree, &args->tree) {
if (entry->value == NULL)
continue;
if (off >= len) {
/* snprintf will have zero terminated. */
return (len);
}
if (strchr(args->values[i], ' ') != NULL)
quotes = "\"";
if (*buf != '\0')
args_print_add(&buf, &len, " -%c ", entry->flag);
else
quotes = "";
off += xsnprintf(buf + off, len - off, "%s-%c %s%s%s",
off != 0 ? " " : "", i, quotes, args->values[i], quotes);
args_print_add(&buf, &len, "-%c ", entry->flag);
if (strchr(entry->value, ' ') != NULL)
args_print_add(&buf, &len, "\"%s\"", entry->value);
else
args_print_add(&buf, &len, "%s", entry->value);
}
/* And finally the argument vector. */
for (i = 0; i < args->argc; i++) {
if (off >= len) {
/* snprintf will have zero terminated. */
return (len);
}
if (*buf != '\0')
args_print_add(&buf, &len, " ");
if (strchr(args->argv[i], ' ') != NULL)
quotes = "\"";
args_print_add(&buf, &len, "\"%s\"", args->argv[i]);
else
quotes = "";
off += xsnprintf(buf + off, len - off, "%s%s%s%s",
off != 0 ? " " : "", quotes, args->argv[i], quotes);
args_print_add(&buf, &len, "%s", args->argv[i]);
}
return (off);
return (buf);
}
/* Return if an argument is present. */
int
args_has(struct args *args, u_char ch)
{
return (bit_test(args->flags, ch));
return (args_find(args, ch) == NULL ? 0 : 1);
}
/* Set argument value. */
/* Set argument value in the arguments tree. */
void
args_set(struct args *args, u_char ch, const char *value)
{
free(args->values[ch]);
struct args_entry *entry;
/* Replace existing argument. */
if ((entry = args_find(args, ch)) != NULL) {
free(entry->value);
entry->value = NULL;
} else {
entry = xcalloc(1, sizeof *entry);
entry->flag = ch;
RB_INSERT(args_tree, &args->tree, entry);
}
if (value != NULL)
args->values[ch] = xstrdup(value);
else
args->values[ch] = NULL;
bit_set(args->flags, ch);
entry->value = xstrdup(value);
}
/* 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]);
struct args_entry *entry;
if ((entry = args_find(args, ch)) == NULL)
return (NULL);
return (entry->value);
}
/* 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)
args_strtonum(struct args *args, u_char ch, long long minval, long long maxval,
char **cause)
{
const char *errstr;
long long ll;
const char *errstr;
long long ll;
struct args_entry *entry;
if (!args_has(args, ch)) {
if ((entry = args_find(args, ch)) == NULL) {
*cause = xstrdup("missing");
return (0);
}
ll = strtonum(args->values[ch], minval, maxval, &errstr);
ll = strtonum(entry->value, minval, maxval, &errstr);
if (errstr != NULL) {
*cause = xstrdup(errstr);
return (0);

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2006 Nicholas Marriott <nicm@users.sourceforge.net>
@ -39,10 +39,10 @@
fatalx("size too big"); \
if ((a)->space == 0) { \
(a)->space = ARRAY_INITIALSPACE(a); \
(a)->list = xrealloc((a)->list, 1, (a)->space); \
(a)->list = xrealloc((a)->list, (a)->space); \
} \
while ((a)->space <= ((a)->num + (n)) * ARRAY_ITEMSIZE(a)) { \
(a)->list = xrealloc((a)->list, 2, (a)->space); \
(a)->list = xreallocarray((a)->list, 2, (a)->space); \
(a)->space *= 2; \
} \
} while (0)

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Joshua Elsasser <josh@elsasser.org>

View File

@ -1,5 +1,4 @@
#!/bin/sh
# $Id$
if [ "x$(uname)" = "xOpenBSD" ]; then
[ -z "$AUTOMAKE_VERSION" ] && export AUTOMAKE_VERSION=1.10

206
cfg.c
View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@ -17,29 +17,95 @@
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h"
#include "tmate.h"
struct cmd_q *cfg_cmd_q;
int cfg_finished;
int cfg_references;
struct causelist cfg_causes;
char *cfg_file;
#ifdef TMATE
char *tmate_cfg_file;
#endif
struct cmd_q *cfg_cmd_q;
int cfg_finished;
int cfg_references;
char **cfg_causes;
u_int cfg_ncauses;
struct client *cfg_client;
void cfg_default_done(struct cmd_q *);
void
set_cfg_file(const char *path)
{
free(cfg_file);
cfg_file = xstrdup(path);
}
void
start_cfg(void)
{
char *cause = NULL;
const char *home;
cfg_cmd_q = cmdq_new(NULL);
cfg_cmd_q->emptyfn = cfg_default_done;
cfg_finished = 0;
cfg_references = 1;
cfg_client = TAILQ_FIRST(&clients);
if (cfg_client != NULL)
cfg_client->references++;
if (access(TMUX_CONF, R_OK) == 0) {
if (load_cfg(TMUX_CONF, cfg_cmd_q, &cause) == -1)
cfg_add_cause("%s: %s", TMUX_CONF, cause);
} else if (errno != ENOENT)
cfg_add_cause("%s: %s", TMUX_CONF, strerror(errno));
if (cfg_file == NULL && (home = find_home()) != NULL) {
xasprintf(&cfg_file, "%s/.tmux.conf", home);
if (access(cfg_file, R_OK) != 0 && errno == ENOENT) {
free(cfg_file);
cfg_file = NULL;
}
}
if (cfg_file != NULL && load_cfg(cfg_file, cfg_cmd_q, &cause) == -1)
cfg_add_cause("%s: %s", cfg_file, cause);
free(cause);
#ifdef TMATE
cause = NULL;
if ((home = find_home()) != NULL) {
xasprintf(&tmate_cfg_file, "%s/.tmate.conf", home);
if (access(tmate_cfg_file, R_OK) != 0 && errno == ENOENT) {
free(tmate_cfg_file);
tmate_cfg_file = NULL;
}
}
if (tmate_cfg_file != NULL && load_cfg(tmate_cfg_file, cfg_cmd_q, &cause) == -1)
cfg_add_cause("%s: %s", cfg_file, cause);
free(cause);
#endif
cmdq_continue(cfg_cmd_q);
}
int
load_cfg(const char *path, struct cmd_q *cmdq, char **cause)
{
FILE *f;
u_int n, found;
char *buf, *copy, *line, *cause1, *msg;
size_t len, oldlen;
char delim[3] = { '\\', '\\', '\0' };
u_int found;
size_t line = 0;
char *buf, *cause1, *p;
struct cmd_list *cmdlist;
log_debug("loading %s", path);
@ -48,107 +114,121 @@ load_cfg(const char *path, struct cmd_q *cmdq, char **cause)
return (-1);
}
n = found = 0;
line = NULL;
while ((buf = fgetln(f, &len))) {
/* Trim \n. */
if (buf[len - 1] == '\n')
len--;
log_debug("%s: %.*s", path, (int)len, buf);
/* Current line is the continuation of the previous one. */
if (line != NULL) {
oldlen = strlen(line);
line = xrealloc(line, 1, oldlen + len + 1);
} else {
oldlen = 0;
line = xmalloc(len + 1);
}
/* Append current line to the previous. */
memcpy(line + oldlen, buf, len);
line[oldlen + len] = '\0';
n++;
/* Continuation: get next line? */
len = strlen(line);
if (len > 0 && line[len - 1] == '\\') {
line[len - 1] = '\0';
/* Ignore escaped backslash at EOL. */
if (len > 1 && line[len - 2] != '\\')
continue;
}
copy = line;
line = NULL;
found = 0;
while ((buf = fparseln(f, NULL, &line, delim, 0)) != NULL) {
log_debug("%s: %s", path, buf);
/* Skip empty lines. */
buf = copy;
while (isspace((u_char)*buf))
buf++;
if (*buf == '\0') {
free(copy);
p = buf;
while (isspace((u_char) *p))
p++;
if (*p == '\0') {
free(buf);
continue;
}
/* Parse and run the command. */
if (cmd_string_parse(buf, &cmdlist, path, n, &cause1) != 0) {
free(copy);
if (cmd_string_parse(p, &cmdlist, path, line, &cause1) != 0) {
free(buf);
if (cause1 == NULL)
continue;
xasprintf(&msg, "%s:%u: %s", path, n, cause1);
ARRAY_ADD(&cfg_causes, msg);
cfg_add_cause("%s:%zu: %s", path, line, cause1);
free(cause1);
continue;
}
free(copy);
free(buf);
if (cmdlist == NULL)
continue;
cmdq_append(cmdq, cmdlist);
cmdq_append(cmdq, cmdlist, NULL);
cmd_list_free(cmdlist);
found++;
}
if (line != NULL)
free(line);
fclose(f);
return (found);
}
void
cfg_default_done(unused struct cmd_q *cmdq)
cfg_default_done(__unused struct cmd_q *cmdq)
{
if (--cfg_references != 0)
return;
cfg_finished = 1;
#ifdef TMATE
tmate_session_start();
#endif
if (!RB_EMPTY(&sessions))
cfg_show_causes(RB_MIN(sessions, &sessions));
cmdq_free(cfg_cmd_q);
cfg_cmd_q = NULL;
if (cfg_client != NULL) {
/*
* The client command queue starts with client_exit set to 1 so
* only continue if not empty (that is, we have been delayed
* during configuration parsing for long enough that the
* MSG_COMMAND has arrived), else the client will exit before
* the MSG_COMMAND which might tell it not to.
*/
if (!TAILQ_EMPTY(&cfg_client->cmdq->queue))
cmdq_continue(cfg_client->cmdq);
server_client_unref(cfg_client);
cfg_client = NULL;
}
}
void
cfg_add_cause(const char *fmt, ...)
{
va_list ap;
char *msg;
va_start(ap, fmt);
xvasprintf(&msg, fmt, ap);
va_end(ap);
cfg_ncauses++;
cfg_causes = xreallocarray(cfg_causes, cfg_ncauses, sizeof *cfg_causes);
cfg_causes[cfg_ncauses - 1] = msg;
}
void
cfg_print_causes(struct cmd_q *cmdq)
{
u_int i;
for (i = 0; i < cfg_ncauses; i++) {
cmdq_print(cmdq, "%s", cfg_causes[i]);
free(cfg_causes[i]);
}
free(cfg_causes);
cfg_causes = NULL;
cfg_ncauses = 0;
}
void
cfg_show_causes(struct session *s)
{
struct window_pane *wp;
char *cause;
u_int i;
if (s == NULL || ARRAY_EMPTY(&cfg_causes))
if (s == NULL || cfg_ncauses == 0)
return;
wp = s->curw->window->active;
window_pane_set_mode(wp, &window_copy_mode);
window_copy_init_for_output(wp);
for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) {
cause = ARRAY_ITEM(&cfg_causes, i);
window_copy_add(wp, "%s", cause);
free(cause);
for (i = 0; i < cfg_ncauses; i++) {
window_copy_add(wp, "%s", cfg_causes[i]);
free(cfg_causes[i]);
}
ARRAY_FREE(&cfg_causes);
free(cfg_causes);
cfg_causes = NULL;
cfg_ncauses = 0;
}

797
client.c

File diff suppressed because it is too large Load Diff

159
clock.c
View File

@ -1,159 +0,0 @@
/* $Id$ */
/*
* 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 <string.h>
#include <time.h>
#include "tmux.h"
const char clock_table[14][5][5] = {
{ { 1,1,1,1,1 }, /* 0 */
{ 1,0,0,0,1 },
{ 1,0,0,0,1 },
{ 1,0,0,0,1 },
{ 1,1,1,1,1 } },
{ { 0,0,0,0,1 }, /* 1 */
{ 0,0,0,0,1 },
{ 0,0,0,0,1 },
{ 0,0,0,0,1 },
{ 0,0,0,0,1 } },
{ { 1,1,1,1,1 }, /* 2 */
{ 0,0,0,0,1 },
{ 1,1,1,1,1 },
{ 1,0,0,0,0 },
{ 1,1,1,1,1 } },
{ { 1,1,1,1,1 }, /* 3 */
{ 0,0,0,0,1 },
{ 1,1,1,1,1 },
{ 0,0,0,0,1 },
{ 1,1,1,1,1 } },
{ { 1,0,0,0,1 }, /* 4 */
{ 1,0,0,0,1 },
{ 1,1,1,1,1 },
{ 0,0,0,0,1 },
{ 0,0,0,0,1 } },
{ { 1,1,1,1,1 }, /* 5 */
{ 1,0,0,0,0 },
{ 1,1,1,1,1 },
{ 0,0,0,0,1 },
{ 1,1,1,1,1 } },
{ { 1,1,1,1,1 }, /* 6 */
{ 1,0,0,0,0 },
{ 1,1,1,1,1 },
{ 1,0,0,0,1 },
{ 1,1,1,1,1 } },
{ { 1,1,1,1,1 }, /* 7 */
{ 0,0,0,0,1 },
{ 0,0,0,0,1 },
{ 0,0,0,0,1 },
{ 0,0,0,0,1 } },
{ { 1,1,1,1,1 }, /* 8 */
{ 1,0,0,0,1 },
{ 1,1,1,1,1 },
{ 1,0,0,0,1 },
{ 1,1,1,1,1 } },
{ { 1,1,1,1,1 }, /* 9 */
{ 1,0,0,0,1 },
{ 1,1,1,1,1 },
{ 0,0,0,0,1 },
{ 1,1,1,1,1 } },
{ { 0,0,0,0,0 }, /* : */
{ 0,0,1,0,0 },
{ 0,0,0,0,0 },
{ 0,0,1,0,0 },
{ 0,0,0,0,0 } },
{ { 1,1,1,1,1 }, /* A */
{ 1,0,0,0,1 },
{ 1,1,1,1,1 },
{ 1,0,0,0,1 },
{ 1,0,0,0,1 } },
{ { 1,1,1,1,1 }, /* P */
{ 1,0,0,0,1 },
{ 1,1,1,1,1 },
{ 1,0,0,0,0 },
{ 1,0,0,0,0 } },
{ { 1,0,0,0,1 }, /* M */
{ 1,1,0,1,1 },
{ 1,0,1,0,1 },
{ 1,0,0,0,1 },
{ 1,0,0,0,1 } },
};
void
clock_draw(struct screen_write_ctx *ctx, int colour, int style)
{
struct screen *s = ctx->s;
struct grid_cell gc;
char tim[64], *ptr;
time_t t;
u_int i, j, x, y, idx;
t = time(NULL);
if (style == 0)
strftime(tim, sizeof tim, "%l:%M %p", localtime(&t));
else
strftime(tim, sizeof tim, "%H:%M", localtime(&t));
screen_write_clearscreen(ctx);
if (screen_size_x(s) < 6 * strlen(tim) || screen_size_y(s) < 6) {
if (screen_size_x(s) >= strlen(tim) && screen_size_y(s) != 0) {
x = (screen_size_x(s) / 2) - (strlen(tim) / 2);
y = screen_size_y(s) / 2;
screen_write_cursormove(ctx, x, y);
memcpy(&gc, &grid_default_cell, sizeof gc);
colour_set_fg(&gc, colour);
screen_write_puts(ctx, &gc, "%s", tim);
}
return;
}
x = (screen_size_x(s) / 2) - 3 * strlen(tim);
y = (screen_size_y(s) / 2) - 3;
memcpy(&gc, &grid_default_cell, sizeof gc);
colour_set_bg(&gc, colour);
for (ptr = tim; *ptr != '\0'; ptr++) {
if (*ptr >= '0' && *ptr <= '9')
idx = *ptr - '0';
else if (*ptr == ':')
idx = 10;
else if (*ptr == 'A')
idx = 11;
else if (*ptr == 'P')
idx = 12;
else if (*ptr == 'M')
idx = 13;
else {
x += 6;
continue;
}
for (j = 0; j < 5; j++) {
for (i = 0; i < 5; i++) {
screen_write_cursormove(ctx, x + i, y + j);
if (clock_table[idx][j][i])
screen_write_putc(ctx, &gc, ' ');
}
}
x += 6;
}
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -18,7 +18,11 @@
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h"
@ -29,82 +33,122 @@
enum cmd_retval cmd_attach_session_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_attach_session_entry = {
"attach-session", "attach",
"drt:", 0, 0,
"[-dr] " CMD_TARGET_SESSION_USAGE,
CMD_CANTNEST|CMD_STARTSERVER|CMD_SENDENVIRON,
NULL,
NULL,
cmd_attach_session_exec
.name = "attach-session",
.alias = "attach",
.args = { "c:dErt:", 0, 0 },
.usage = "[-dEr] [-c working-directory] " CMD_TARGET_SESSION_USAGE,
.tflag = CMD_SESSION_WITHPANE,
.flags = CMD_STARTSERVER,
.exec = cmd_attach_session_exec
};
enum cmd_retval
cmd_attach_session(struct cmd_q *cmdq, const char* tflag, int dflag, int rflag)
cmd_attach_session(struct cmd_q *cmdq, int dflag, int rflag, const char *cflag,
int Eflag)
{
struct session *s;
struct client *c;
const char *update;
char *cause;
u_int i;
struct session *s = cmdq->state.tflag.s;
struct client *c = cmdq->client, *c_loop;
struct winlink *wl = cmdq->state.tflag.wl;
struct window_pane *wp = cmdq->state.tflag.wp;
const char *update;
char *cause, *cwd;
struct format_tree *ft;
if (RB_EMPTY(&sessions)) {
cmdq_error(cmdq, "no sessions");
return (CMD_RETURN_ERROR);
}
if ((s = cmd_find_session(cmdq, tflag, 1)) == NULL)
return (CMD_RETURN_ERROR);
if (cmdq->client == NULL)
if (c == NULL)
return (CMD_RETURN_NORMAL);
if (server_client_check_nested(c)) {
cmdq_error(cmdq, "sessions should be nested with care, "
"unset $TMUX to force");
return (CMD_RETURN_ERROR);
}
if (cmdq->client->session != NULL) {
if (wl != NULL) {
if (wp != NULL)
window_set_active_pane(wp->window, wp);
session_set_current(s, wl);
}
if (cflag != NULL) {
ft = format_create(cmdq, 0);
format_defaults(ft, c, s, wl, wp);
cwd = format_expand(ft, cflag);
format_free(ft);
free((void *)s->cwd);
s->cwd = cwd;
}
if (c->session != NULL) {
if (dflag) {
/*
* Can't use server_write_session in case attaching to
* the same session as currently attached to.
*/
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session != s)
TAILQ_FOREACH(c_loop, &clients, entry) {
if (c_loop->session != s || c == c_loop)
continue;
if (c == cmdq->client)
continue;
server_write_client(c, MSG_DETACH, NULL, 0);
server_client_detach(c_loop, MSG_DETACH);
}
}
cmdq->client->session = s;
notify_attached_session_changed(cmdq->client);
session_update_activity(s);
server_redraw_client(cmdq->client);
if (!Eflag) {
update = options_get_string(s->options,
"update-environment");
environ_update(update, c->environ, s->environ);
}
c->session = s;
server_client_set_key_table(c, NULL);
status_timer_start(c);
notify_attached_session_changed(c);
session_update_activity(s, NULL);
gettimeofday(&s->last_attached_time, NULL);
server_redraw_client(c);
s->curw->flags &= ~WINLINK_ALERTFLAGS;
} else {
if (server_client_open(cmdq->client, s, &cause) != 0) {
if (server_client_open(c, &cause) != 0) {
cmdq_error(cmdq, "open terminal failed: %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
if (rflag)
cmdq->client->flags |= CLIENT_READONLY;
c->flags |= CLIENT_READONLY;
if (dflag)
server_write_session(s, MSG_DETACH, NULL, 0);
if (dflag) {
TAILQ_FOREACH(c_loop, &clients, entry) {
if (c_loop->session != s || c == c_loop)
continue;
server_client_detach(c_loop, MSG_DETACH);
}
}
update = options_get_string(&s->options, "update-environment");
environ_update(update, &cmdq->client->environ, &s->environ);
if (!Eflag) {
update = options_get_string(s->options,
"update-environment");
environ_update(update, c->environ, s->environ);
}
cmdq->client->session = s;
notify_attached_session_changed(cmdq->client);
session_update_activity(s);
server_redraw_client(cmdq->client);
c->session = s;
server_client_set_key_table(c, NULL);
status_timer_start(c);
notify_attached_session_changed(c);
session_update_activity(s, NULL);
gettimeofday(&s->last_attached_time, NULL);
server_redraw_client(c);
s->curw->flags &= ~WINLINK_ALERTFLAGS;
server_write_ready(cmdq->client);
if (~c->flags & CLIENT_CONTROL)
proc_send(c->peer, MSG_READY, -1, NULL, 0);
hooks_run(c->session->hooks, c, NULL, "client-attached");
cmdq->client_exit = 0;
}
recalculate_sizes();
alerts_check_session(s);
server_update_socket();
return (CMD_RETURN_NORMAL);
@ -115,6 +159,6 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
return (cmd_attach_session(cmdq, args_get(args, 't'),
args_has(args, 'd'), args_has(args, 'r')));
return (cmd_attach_session(cmdq, args_has(args, 'd'),
args_has(args, 'r'), args_get(args, 'c'), args_has(args, 'E')));
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -27,33 +27,22 @@
* Bind a key to a command, this recurses through cmd_*.
*/
enum cmd_retval cmd_bind_key_check(struct args *);
enum cmd_retval cmd_bind_key_exec(struct cmd *, struct cmd_q *);
enum cmd_retval cmd_bind_key_table(struct cmd *, struct cmd_q *, int);
enum cmd_retval cmd_bind_key_mode_table(struct cmd *, struct cmd_q *,
key_code);
const struct cmd_entry cmd_bind_key_entry = {
"bind-key", "bind",
"cnrt:", 1, -1,
"[-cnr] [-t key-table] key command [arguments]",
0,
NULL,
cmd_bind_key_check,
cmd_bind_key_exec
};
.name = "bind-key",
.alias = "bind",
enum cmd_retval
cmd_bind_key_check(struct args *args)
{
if (args_has(args, 't')) {
if (args->argc != 2 && args->argc != 3)
return (CMD_RETURN_ERROR);
} else {
if (args->argc < 2)
return (CMD_RETURN_ERROR);
}
return (CMD_RETURN_NORMAL);
}
.args = { "cnrt:T:", 1, -1 },
.usage = "[-cnr] [-t mode-table] [-T key-table] key command "
"[arguments]",
.flags = 0,
.exec = cmd_bind_key_exec
};
enum cmd_retval
cmd_bind_key_exec(struct cmd *self, struct cmd_q *cmdq)
@ -61,16 +50,36 @@ cmd_bind_key_exec(struct cmd *self, struct cmd_q *cmdq)
struct args *args = self->args;
char *cause;
struct cmd_list *cmdlist;
int key;
key_code key;
const char *tablename;
if (args_has(args, 't')) {
if (args->argc != 2 && args->argc != 3) {
cmdq_error(cmdq, "not enough arguments");
return (CMD_RETURN_ERROR);
}
} else {
if (args->argc < 2) {
cmdq_error(cmdq, "not enough arguments");
return (CMD_RETURN_ERROR);
}
}
key = key_string_lookup_string(args->argv[0]);
if (key == KEYC_NONE) {
if (key == KEYC_NONE || key == KEYC_UNKNOWN) {
cmdq_error(cmdq, "unknown key: %s", args->argv[0]);
return (CMD_RETURN_ERROR);
}
if (args_has(args, 't'))
return (cmd_bind_key_table(self, cmdq, key));
return (cmd_bind_key_mode_table(self, cmdq, key));
if (args_has(args, 'T'))
tablename = args_get(args, 'T');
else if (args_has(args, 'n'))
tablename = "root";
else
tablename = "prefix";
cmdlist = cmd_list_parse(args->argc - 1, args->argv + 1, NULL, 0,
&cause);
@ -80,14 +89,12 @@ cmd_bind_key_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_ERROR);
}
if (!args_has(args, 'n'))
key |= KEYC_PREFIX;
key_bindings_add(key, args_has(args, 'r'), cmdlist);
key_bindings_add(tablename, key, args_has(args, 'r'), cmdlist);
return (CMD_RETURN_NORMAL);
}
enum cmd_retval
cmd_bind_key_table(struct cmd *self, struct cmd_q *cmdq, int key)
cmd_bind_key_mode_table(struct cmd *self, struct cmd_q *cmdq, key_code key)
{
struct args *args = self->args;
const char *tablename;
@ -108,18 +115,34 @@ cmd_bind_key_table(struct cmd *self, struct cmd_q *cmdq, int key)
return (CMD_RETURN_ERROR);
}
if (cmd != MODEKEYCOPY_COPYPIPE) {
if (args->argc != 2) {
cmdq_error(cmdq, "no argument allowed");
return (CMD_RETURN_ERROR);
switch (cmd) {
case MODEKEYCOPY_APPENDSELECTION:
case MODEKEYCOPY_COPYSELECTION:
case MODEKEYCOPY_STARTNAMEDBUFFER:
if (args->argc == 2)
arg = NULL;
else {
arg = args->argv[2];
if (strcmp(arg, "-x") != 0) {
cmdq_error(cmdq, "unknown argument");
return (CMD_RETURN_ERROR);
}
}
arg = NULL;
} else {
break;
case MODEKEYCOPY_COPYPIPE:
if (args->argc != 3) {
cmdq_error(cmdq, "no argument given");
return (CMD_RETURN_ERROR);
}
arg = args->argv[2];
break;
default:
if (args->argc != 2) {
cmdq_error(cmdq, "no argument allowed");
return (CMD_RETURN_ERROR);
}
arg = NULL;
break;
}
mtmp.key = key;

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@ -26,16 +26,22 @@
* Break pane off into a window.
*/
#define BREAK_PANE_TEMPLATE "#{session_name}:#{window_index}.#{pane_index}"
enum cmd_retval cmd_break_pane_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_break_pane_entry = {
"break-pane", "breakp",
"dPF:t:", 0, 0,
"[-dP] [-F format] " CMD_TARGET_PANE_USAGE,
0,
NULL,
NULL,
cmd_break_pane_exec
.name = "break-pane",
.alias = "breakp",
.args = { "dPF:s:t:", 0, 0 },
.usage = "[-dP] [-F format] " CMD_SRCDST_PANE_USAGE,
.sflag = CMD_PANE,
.tflag = CMD_WINDOW_INDEX,
.flags = 0,
.exec = cmd_break_pane_exec
};
enum cmd_retval
@ -46,68 +52,61 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_ERROR);
#else
struct args *args = self->args;
struct winlink *wl;
struct session *s;
struct window_pane *wp;
struct window *w;
struct winlink *wl = cmdq->state.sflag.wl;
struct session *src_s = cmdq->state.sflag.s;
struct session *dst_s = cmdq->state.tflag.s;
struct window_pane *wp = cmdq->state.sflag.wp;
struct window *w = wl->window;
char *name;
char *cause;
int base_idx;
struct client *c;
int idx = cmdq->state.tflag.idx;
struct format_tree *ft;
const char *template;
char *cp;
if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL)
return (CMD_RETURN_ERROR);
if (window_count_panes(wl->window) == 1) {
cmdq_error(cmdq, "can't break with only one pane");
if (idx != -1 && winlink_find_by_index(&dst_s->windows, idx) != NULL) {
cmdq_error(cmdq, "index %d already in use", idx);
return (CMD_RETURN_ERROR);
}
w = wl->window;
if (window_count_panes(w) == 1) {
cmdq_error(cmdq, "can't break with only one pane");
return (CMD_RETURN_ERROR);
}
server_unzoom_window(w);
TAILQ_REMOVE(&w->panes, wp, entry);
if (wp == w->active) {
w->active = w->last;
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;
window_lost_pane(w, wp);
layout_close_pane(wp);
w = wp->window = window_create1(s->sx, s->sy);
w = wp->window = window_create1(dst_s->sx, dst_s->sy);
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
w->active = wp;
name = default_window_name(w);
window_set_name(w, name);
free(name);
layout_init(w, wp);
wp->flags |= PANE_CHANGED;
base_idx = options_get_number(&s->options, "base-index");
wl = session_attach(s, w, -1 - base_idx, &cause); /* can't fail */
if (idx == -1)
idx = -1 - options_get_number(dst_s->options, "base-index");
wl = session_attach(dst_s, w, idx, &cause); /* can't fail */
if (!args_has(self->args, 'd'))
session_select(s, wl->idx);
session_select(dst_s, wl->idx);
server_redraw_session(s);
server_status_session_group(s);
server_redraw_session(src_s);
if (src_s != dst_s)
server_redraw_session(dst_s);
server_status_session_group(src_s);
if (src_s != dst_s)
server_status_session_group(dst_s);
if (args_has(args, 'P')) {
if ((template = args_get(args, 'F')) == NULL)
template = BREAK_PANE_TEMPLATE;
ft = format_create();
if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
format_client(ft, c);
format_session(ft, s);
format_winlink(ft, s, wl);
format_window_pane(ft, wp);
ft = format_create(cmdq, 0);
format_defaults(ft, cmdq->state.c, dst_s, wl, wp);
cp = format_expand(ft, template);
cmdq_print(cmdq, "%s", cp);

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Jonathan Alvarado <radobobo@users.sourceforge.net>
@ -36,20 +36,23 @@ char *cmd_capture_pane_history(struct args *, struct cmd_q *,
struct window_pane *, size_t *);
const struct cmd_entry cmd_capture_pane_entry = {
"capture-pane", "capturep",
"ab:CeE:JpPqS:t:", 0, 0,
"[-aCeJpPq] [-b buffer-index] [-E end-line] [-S start-line]"
CMD_TARGET_PANE_USAGE,
0,
NULL,
NULL,
cmd_capture_pane_exec
.name = "capture-pane",
.alias = "capturep",
.args = { "ab:CeE:JpPqS:t:", 0, 0 },
.usage = "[-aCeJpPq] " CMD_BUFFER_USAGE " [-E end-line] "
"[-S start-line]" CMD_TARGET_PANE_USAGE,
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_capture_pane_exec
};
char *
cmd_capture_pane_append(char *buf, size_t *len, char *line, size_t linelen)
{
buf = xrealloc(buf, 1, *len + linelen + 1);
buf = xrealloc(buf, *len + linelen + 1);
memcpy(buf + *len, line, linelen);
*len += linelen;
return (buf);
@ -59,15 +62,17 @@ char *
cmd_capture_pane_pending(struct args *args, struct window_pane *wp,
size_t *len)
{
char *buf, *line, tmp[5];
size_t linelen;
u_int i;
struct evbuffer *pending;
char *buf, *line, tmp[5];
size_t linelen;
u_int i;
if (wp->ictx.since_ground == NULL)
pending = input_pending(wp);
if (pending == NULL)
return (xstrdup(""));
line = EVBUFFER_DATA(wp->ictx.since_ground);
linelen = EVBUFFER_LENGTH(wp->ictx.since_ground);
line = EVBUFFER_DATA(pending);
linelen = EVBUFFER_LENGTH(pending);
buf = xstrdup("");
if (args_has(args, 'C')) {
@ -76,7 +81,7 @@ cmd_capture_pane_pending(struct args *args, struct window_pane *wp,
tmp[0] = line[i];
tmp[1] = '\0';
} else
xsnprintf(tmp, sizeof tmp, "\\%03o", line[i]);
xsnprintf(tmp, sizeof tmp, "\\%03hho", line[i]);
buf = cmd_capture_pane_append(buf, len, tmp,
strlen(tmp));
}
@ -95,6 +100,7 @@ cmd_capture_pane_history(struct args *args, struct cmd_q *cmdq,
int n, with_codes, escape_c0, join_lines;
u_int i, sx, top, bottom, tmp;
char *cause, *buf, *line;
const char *Sflag, *Eflag;
size_t linelen;
sx = screen_size_x(&wp->base);
@ -110,27 +116,37 @@ cmd_capture_pane_history(struct args *args, struct cmd_q *cmdq,
} else
gd = wp->base.grid;
n = args_strtonum(args, 'S', INT_MIN, SHRT_MAX, &cause);
if (cause != NULL) {
top = gd->hsize;
free(cause);
} else if (n < 0 && (u_int) -n > gd->hsize)
Sflag = args_get(args, 'S');
if (Sflag != NULL && strcmp(Sflag, "-") == 0)
top = 0;
else
top = gd->hsize + n;
if (top > gd->hsize + gd->sy - 1)
top = gd->hsize + gd->sy - 1;
else {
n = args_strtonum(args, 'S', INT_MIN, SHRT_MAX, &cause);
if (cause != NULL) {
top = gd->hsize;
free(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;
free(cause);
} else if (n < 0 && (u_int) -n > gd->hsize)
bottom = 0;
else
bottom = gd->hsize + n;
if (bottom > gd->hsize + gd->sy - 1)
Eflag = args_get(args, 'E');
if (Eflag != NULL && strcmp(Eflag, "-") == 0)
bottom = gd->hsize + gd->sy - 1;
else {
n = args_strtonum(args, 'E', INT_MIN, SHRT_MAX, &cause);
if (cause != NULL) {
bottom = gd->hsize + gd->sy - 1;
free(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;
@ -164,15 +180,11 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
struct window_pane *wp;
struct window_pane *wp = cmdq->state.tflag.wp;
char *buf, *cause;
int buffer;
u_int limit;
const char *bufname;
size_t len;
if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL)
return (CMD_RETURN_ERROR);
len = 0;
if (args_has(args, 'P'))
buf = cmd_capture_pane_pending(args, wp, &len);
@ -186,29 +198,22 @@ cmd_capture_pane_exec(struct cmd *self, struct cmd_q *cmdq)
if (c == NULL ||
(c->session != NULL && !(c->flags & CLIENT_CONTROL))) {
cmdq_error(cmdq, "can't write to stdout");
free(buf);
return (CMD_RETURN_ERROR);
}
evbuffer_add(c->stdout_data, buf, len);
free(buf);
if (args_has(args, 'P') && len > 0)
evbuffer_add(c->stdout_data, "\n", 1);
server_push_stdout(c);
server_client_push_stdout(c);
} else {
limit = options_get_number(&global_options, "buffer-limit");
if (!args_has(args, 'b')) {
paste_add(&global_buffers, buf, len, limit);
return (CMD_RETURN_NORMAL);
}
bufname = NULL;
if (args_has(args, 'b'))
bufname = args_get(args, 'b');
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
if (cause != NULL) {
cmdq_error(cmdq, "buffer %s", cause);
free(buf);
if (paste_set(buf, len, bufname, &cause) != 0) {
cmdq_error(cmdq, "%s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
if (paste_replace(&global_buffers, buffer, buf, len) != 0) {
cmdq_error(cmdq, "no buffer %d", buffer);
free(buf);
return (CMD_RETURN_ERROR);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net>
@ -27,31 +27,37 @@
* Enter choice mode to choose a buffer.
*/
#define CHOOSE_BUFFER_TEMPLATE \
"#{buffer_name}: #{buffer_size} bytes: #{buffer_sample}"
enum cmd_retval cmd_choose_buffer_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_choose_buffer_entry = {
"choose-buffer", NULL,
"F:t:", 0, 1,
CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
0,
NULL,
NULL,
cmd_choose_buffer_exec
.name = "choose-buffer",
.alias = NULL,
.args = { "F:t:", 0, 1 },
.usage = CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_choose_buffer_exec
};
enum cmd_retval
cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
struct client *c = cmdq->state.c;
struct winlink *wl = cmdq->state.tflag.wl;
struct window_choose_data *cdata;
struct winlink *wl;
struct paste_buffer *pb;
char *action, *action_data;
const char *template;
u_int idx;
if ((c = cmd_current_client(cmdq)) == NULL) {
if (c == NULL) {
cmdq_error(cmdq, "no client available");
return (CMD_RETURN_ERROR);
}
@ -59,10 +65,7 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
if ((template = args_get(args, 'F')) == NULL)
template = CHOOSE_BUFFER_TEMPLATE;
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR);
if (paste_get_top(&global_buffers) == NULL)
if (paste_get_top(NULL) == NULL)
return (CMD_RETURN_NORMAL);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
@ -74,19 +77,20 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
action = xstrdup("paste-buffer -b '%%'");
idx = 0;
while ((pb = paste_walk_stack(&global_buffers, &idx)) != NULL) {
pb = NULL;
while ((pb = paste_walk(pb)) != NULL) {
cdata = window_choose_data_create(TREE_OTHER, c, c->session);
cdata->idx = idx - 1;
cdata->idx = idx;
cdata->ft_template = xstrdup(template);
format_add(cdata->ft, "line", "%u", idx - 1);
format_paste_buffer(cdata->ft, pb);
format_defaults_paste_buffer(cdata->ft, pb);
xasprintf(&action_data, "%u", idx - 1);
xasprintf(&action_data, "%s", paste_buffer_name(pb));
cdata->command = cmd_template_replace(action, action_data, 1);
free(action_data);
window_choose_add(wl->window->active, cdata);
idx++;
}
free(action);

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@ -27,18 +27,27 @@
* Enter choice mode to choose a client.
*/
#define CHOOSE_CLIENT_TEMPLATE \
"#{client_tty}: #{session_name} " \
"[#{client_width}x#{client_height} #{client_termname}]" \
"#{?client_utf8, (utf8),}#{?client_readonly, (ro),} " \
"(last used #{t:client_activity})"
enum cmd_retval cmd_choose_client_exec(struct cmd *, struct cmd_q *);
void cmd_choose_client_callback(struct window_choose_data *);
const struct cmd_entry cmd_choose_client_entry = {
"choose-client", NULL,
"F:t:", 0, 1,
CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
0,
NULL,
NULL,
cmd_choose_client_exec
.name = "choose-client",
.alias = NULL,
.args = { "F:t:", 0, 1 },
.usage = CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_choose_client_exec
};
struct cmd_choose_client_data {
@ -49,22 +58,19 @@ enum cmd_retval
cmd_choose_client_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
struct client *c = cmdq->state.c;
struct client *c1;
struct window_choose_data *cdata;
struct winlink *wl;
struct winlink *wl = cmdq->state.tflag.wl;
const char *template;
char *action;
u_int i, idx, cur;
u_int idx, cur;
if ((c = cmd_current_client(cmdq)) == NULL) {
if (c == NULL) {
cmdq_error(cmdq, "no client available");
return (CMD_RETURN_ERROR);
}
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
return (CMD_RETURN_NORMAL);
@ -77,25 +83,24 @@ cmd_choose_client_exec(struct cmd *self, struct cmd_q *cmdq)
action = xstrdup("detach-client -t '%%'");
cur = idx = 0;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c1 = ARRAY_ITEM(&clients, i);
if (c1 == NULL || c1->session == NULL || c1->tty.path == NULL)
TAILQ_FOREACH(c1, &clients, entry) {
if (c1->session == NULL || c1->tty.path == NULL)
continue;
if (c1 == cmdq->client)
cur = idx;
idx++;
cdata = window_choose_data_create(TREE_OTHER, c, c->session);
cdata->idx = i;
cdata->idx = idx;
cdata->ft_template = xstrdup(template);
format_add(cdata->ft, "line", "%u", i);
format_session(cdata->ft, c1->session);
format_client(cdata->ft, c1);
format_add(cdata->ft, "line", "%u", idx);
format_defaults(cdata->ft, c1, NULL, NULL, NULL);
cdata->command = cmd_template_replace(action, c1->tty.path, 1);
window_choose_add(wl->window->active, cdata);
idx++;
}
free(action);
@ -109,15 +114,19 @@ void
cmd_choose_client_callback(struct window_choose_data *cdata)
{
struct client *c;
u_int idx;
if (cdata == NULL)
return;
if (cdata->start_client->flags & CLIENT_DEAD)
return;
if (cdata->idx > ARRAY_LENGTH(&clients) - 1)
return;
c = ARRAY_ITEM(&clients, cdata->idx);
idx = 0;
TAILQ_FOREACH(c, &clients, entry) {
if (idx == cdata->idx)
break;
idx++;
}
if (c == NULL || c->session == NULL)
return;

View File

@ -1,98 +0,0 @@
/* $Id$ */
/*
* Copyright (c) 2012 Thomas Adam <thomas@xteddy.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 <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
#define CMD_CHOOSE_LIST_DEFAULT_TEMPLATE "run-shell '%%'"
/*
* Enter choose mode to choose a custom list.
*/
enum cmd_retval cmd_choose_list_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_choose_list_entry = {
"choose-list", NULL,
"l:t:", 0, 1,
"[-l items] " CMD_TARGET_WINDOW_USAGE "[template]",
0,
NULL,
NULL,
cmd_choose_list_exec
};
enum cmd_retval
cmd_choose_list_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
struct winlink *wl;
const char *list1;
char *template, *item, *copy, *list;
u_int idx;
if ((c = cmd_current_client(cmdq)) == NULL) {
cmdq_error(cmdq, "no client available");
return (CMD_RETURN_ERROR);
}
if ((list1 = args_get(args, 'l')) == NULL)
return (CMD_RETURN_ERROR);
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
return (CMD_RETURN_NORMAL);
if (args->argc != 0)
template = xstrdup(args->argv[0]);
else
template = xstrdup(CMD_CHOOSE_LIST_DEFAULT_TEMPLATE);
copy = list = xstrdup(list1);
idx = 0;
while ((item = strsep(&list, ",")) != NULL)
{
if (*item == '\0') /* no empty entries */
continue;
window_choose_add_item(wl->window->active, c, wl, item,
template, idx);
idx++;
}
free(copy);
if (idx == 0) {
free(template);
window_pane_reset_mode(wl->window->active);
return (CMD_RETURN_ERROR);
}
window_choose_ready(wl->window->active, 0, NULL);
free(template);
return (CMD_RETURN_NORMAL);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2012 Thomas Adam <thomas@xteddy.org>
@ -32,46 +32,64 @@
* Enter choice mode to choose a session and/or window.
*/
#define CHOOSE_TREE_SESSION_TEMPLATE \
"#{session_name}: #{session_windows} windows" \
"#{?session_grouped, (group ,}" \
"#{session_group}#{?session_grouped,),}" \
"#{?session_attached, (attached),}"
#define CHOOSE_TREE_WINDOW_TEMPLATE \
"#{window_index}: #{window_name}#{window_flags} " \
"\"#{pane_title}\""
enum cmd_retval cmd_choose_tree_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_choose_tree_entry = {
"choose-tree", NULL,
"S:W:swub:c:t:", 0, 1,
"[-suw] [-b session-template] [-c window template] [-S format] " \
"[-W format] " CMD_TARGET_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_choose_tree_exec
.name = "choose-tree",
.alias = NULL,
.args = { "S:W:swub:c:t:", 0, 1 },
.usage = "[-suw] [-b session-template] [-c window template] "
"[-S format] [-W format] " CMD_TARGET_WINDOW_USAGE,
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_choose_tree_exec
};
const struct cmd_entry cmd_choose_session_entry = {
"choose-session", NULL,
"F:t:", 0, 1,
CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
0,
NULL,
NULL,
cmd_choose_tree_exec
.name = "choose-session",
.alias = NULL,
.args = { "F:t:", 0, 1 },
.usage = CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_choose_tree_exec
};
const struct cmd_entry cmd_choose_window_entry = {
"choose-window", NULL,
"F:t:", 0, 1,
CMD_TARGET_WINDOW_USAGE "[-F format] [template]",
0,
NULL,
NULL,
cmd_choose_tree_exec
.name = "choose-window",
.alias = NULL,
.args = { "F:t:", 0, 1 },
.usage = CMD_TARGET_WINDOW_USAGE "[-F format] [template]",
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_choose_tree_exec
};
enum cmd_retval
cmd_choose_tree_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct winlink *wl, *wm;
struct session *s, *s2;
struct client *c;
struct client *c = cmdq->state.c;
struct winlink *wl = cmdq->state.tflag.wl, *wm;
struct session *s = cmdq->state.tflag.s, *s2;
struct window_choose_data *wcd = NULL;
const char *ses_template, *win_template;
char *final_win_action, *cur_win_template;
@ -84,17 +102,11 @@ cmd_choose_tree_exec(struct cmd *self, struct cmd_q *cmdq)
ses_template = win_template = NULL;
ses_action = win_action = NULL;
if ((c = cmd_current_client(cmdq)) == NULL) {
if (c == NULL) {
cmdq_error(cmdq, "no client available");
return (CMD_RETURN_ERROR);
}
if ((s = c->session) == NULL)
return (CMD_RETURN_ERROR);
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR);
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
return (CMD_RETURN_NORMAL);
@ -232,8 +244,10 @@ windows_only:
window_choose_ready(wl->window->active, cur_win, NULL);
if (args_has(args, 'u'))
if (args_has(args, 'u')) {
window_choose_expand_all(wl->window->active);
window_choose_set_current(wl->window->active, cur_win);
}
return (CMD_RETURN_NORMAL);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@ -27,28 +27,29 @@
enum cmd_retval cmd_clear_history_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_clear_history_entry = {
"clear-history", "clearhist",
"t:", 0, 0,
CMD_TARGET_PANE_USAGE,
0,
NULL,
NULL,
cmd_clear_history_exec
.name = "clear-history",
.alias = "clearhist",
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_PANE_USAGE,
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_clear_history_exec
};
enum cmd_retval
cmd_clear_history_exec(struct cmd *self, struct cmd_q *cmdq)
cmd_clear_history_exec(__unused struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct window_pane *wp;
struct window_pane *wp = cmdq->state.tflag.wp;
struct grid *gd;
if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL)
return (CMD_RETURN_ERROR);
gd = wp->base.grid;
gd = cmdq->state.tflag.wp->base.grid;
grid_move_lines(gd, 0, gd->hsize, gd->sy);
gd->hsize = 0;
if (wp->mode == &window_copy_mode)
window_pane_reset_mode(wp);
grid_clear_history(gd);
return (CMD_RETURN_NORMAL);
}

View File

@ -1,51 +0,0 @@
/* $Id$ */
/*
* 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"
/*
* Enter clock mode.
*/
enum cmd_retval cmd_clock_mode_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_clock_mode_entry = {
"clock-mode", NULL,
"t:", 0, 0,
CMD_TARGET_PANE_USAGE,
0,
NULL,
NULL,
cmd_clock_mode_exec
};
enum cmd_retval
cmd_clock_mode_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct window_pane *wp;
if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL)
return (CMD_RETURN_ERROR);
window_pane_set_mode(wp, &window_clock_mode);
return (CMD_RETURN_NORMAL);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@ -29,21 +29,23 @@
* Prompt for command in client.
*/
void cmd_command_prompt_key_binding(struct cmd *, int);
int cmd_command_prompt_check(struct args *);
enum cmd_retval cmd_command_prompt_exec(struct cmd *, struct cmd_q *);
int cmd_command_prompt_callback(void *, const char *);
void cmd_command_prompt_free(void *);
const struct cmd_entry cmd_command_prompt_entry = {
"command-prompt", NULL,
"I:p:t:", 0, 1,
"[-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " [template]",
0,
cmd_command_prompt_key_binding,
NULL,
cmd_command_prompt_exec
.name = "command-prompt",
.alias = NULL,
.args = { "I:p:t:", 0, 1 },
.usage = "[-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " "
"[template]",
.tflag = CMD_CLIENT,
.flags = 0,
.exec = cmd_command_prompt_exec
};
struct cmd_command_prompt_cdata {
@ -56,47 +58,16 @@ struct cmd_command_prompt_cdata {
int idx;
};
void
cmd_command_prompt_key_binding(struct cmd *self, int key)
{
switch (key) {
case '$':
self->args = args_create(1, "rename-session '%%'");
args_set(self->args, 'I', "#S");
break;
case ',':
self->args = args_create(1, "rename-window '%%'");
args_set(self->args, 'I', "#W");
break;
case '.':
self->args = args_create(1, "move-window -t '%%'");
break;
case 'f':
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;
}
}
enum cmd_retval
cmd_command_prompt_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
const char *inputs, *prompts;
struct cmd_command_prompt_cdata *cdata;
struct client *c;
struct client *c = cmdq->state.c;
char *prompt, *ptr, *input = NULL;
size_t n;
if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
if (c->prompt_string != NULL)
return (CMD_RETURN_NORMAL);
@ -183,7 +154,7 @@ cmd_command_prompt_callback(void *data, const char *s)
return (0);
}
cmdq_run(c->cmdq, cmdlist);
cmdq_run(c->cmdq, cmdlist, NULL);
cmd_list_free(cmdlist);
if (c->prompt_callbackfn != (void *) &cmd_command_prompt_callback)

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@ -16,6 +16,8 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
@ -26,20 +28,22 @@
* Asks for confirmation before executing a command.
*/
void cmd_confirm_before_key_binding(struct cmd *, int);
enum cmd_retval cmd_confirm_before_exec(struct cmd *, struct cmd_q *);
int cmd_confirm_before_callback(void *, const char *);
void cmd_confirm_before_free(void *);
const struct cmd_entry cmd_confirm_before_entry = {
"confirm-before", "confirm",
"p:t:", 1, 1,
"[-p prompt] " CMD_TARGET_CLIENT_USAGE " command",
0,
cmd_confirm_before_key_binding,
NULL,
cmd_confirm_before_exec
.name = "confirm-before",
.alias = "confirm",
.args = { "p:t:", 1, 1 },
.usage = "[-p prompt] " CMD_TARGET_CLIENT_USAGE " command",
.tflag = CMD_CLIENT,
.flags = 0,
.exec = cmd_confirm_before_exec
};
struct cmd_confirm_before_data {
@ -47,36 +51,15 @@ struct cmd_confirm_before_data {
struct client *client;
};
void
cmd_confirm_before_key_binding(struct cmd *self, int key)
{
switch (key) {
case '&':
self->args = args_create(1, "kill-window");
args_set(self->args, 'p', "kill-window #W? (y/n)");
break;
case 'x':
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;
}
}
enum cmd_retval
cmd_confirm_before_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct cmd_confirm_before_data *cdata;
struct client *c;
struct client *c = cmdq->state.c;
char *cmd, *copy, *new_prompt, *ptr;
const char *prompt;
if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
if ((prompt = args_get(args, 'p')) != NULL)
xasprintf(&new_prompt, "%s ", prompt);
else {
@ -124,7 +107,7 @@ cmd_confirm_before_callback(void *data, const char *s)
return (0);
}
cmdq_run(c->cmdq, cmdlist);
cmdq_run(c->cmdq, cmdlist, NULL);
cmd_list_free(cmdlist);
return (0);
@ -136,7 +119,7 @@ cmd_confirm_before_free(void *data)
struct cmd_confirm_before_data *cdata = data;
struct client *c = cdata->client;
c->references--;
server_client_unref(c);
free(cdata->cmd);
free(cdata);

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -21,42 +21,65 @@
#include "tmux.h"
/*
* Enter copy mode.
* Enter copy or clock mode.
*/
void cmd_copy_mode_key_binding(struct cmd *, int);
enum cmd_retval cmd_copy_mode_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_copy_mode_entry = {
"copy-mode", NULL,
"t:u", 0, 0,
"[-u] " CMD_TARGET_PANE_USAGE,
0,
cmd_copy_mode_key_binding,
NULL,
cmd_copy_mode_exec
.name = "copy-mode",
.alias = NULL,
.args = { "Met:u", 0, 0 },
.usage = "[-Mu] " CMD_TARGET_PANE_USAGE,
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_copy_mode_exec
};
void
cmd_copy_mode_key_binding(struct cmd *self, int key)
{
self->args = args_create(0);
if (key == KEYC_PPAGE)
args_set(self->args, 'u', NULL);
}
const struct cmd_entry cmd_clock_mode_entry = {
.name = "clock-mode",
.alias = NULL,
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_PANE_USAGE,
.flags = 0,
.exec = cmd_copy_mode_exec
};
enum cmd_retval
cmd_copy_mode_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct window_pane *wp;
struct client *c = cmdq->client;
struct session *s;
struct window_pane *wp = cmdq->state.tflag.wp;
if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL)
return (CMD_RETURN_ERROR);
if (args_has(args, 'M')) {
if ((wp = cmd_mouse_pane(&cmdq->item->mouse, &s, NULL)) == NULL)
return (CMD_RETURN_NORMAL);
if (c == NULL || c->session != s)
return (CMD_RETURN_NORMAL);
}
if (window_pane_set_mode(wp, &window_copy_mode) != 0)
if (self->entry == &cmd_clock_mode_entry) {
window_pane_set_mode(wp, &window_clock_mode);
return (CMD_RETURN_NORMAL);
window_copy_init_from_pane(wp);
}
if (wp->mode != &window_copy_mode) {
if (window_pane_set_mode(wp, &window_copy_mode) != 0)
return (CMD_RETURN_NORMAL);
window_copy_init_from_pane(wp, args_has(self->args, 'e'));
}
if (args_has(args, 'M')) {
if (wp->mode != NULL && wp->mode != &window_copy_mode)
return (CMD_RETURN_NORMAL);
window_copy_start_drag(c, &cmdq->item->mouse);
}
if (wp->mode == &window_copy_mode && args_has(self->args, 'u'))
window_copy_pageup(wp);

View File

@ -1,66 +0,0 @@
/* $Id$ */
/*
* 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 <stdlib.h>
#include "tmux.h"
/*
* Delete a paste buffer.
*/
enum cmd_retval cmd_delete_buffer_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_delete_buffer_entry = {
"delete-buffer", "deleteb",
"b:", 0, 0,
CMD_BUFFER_USAGE,
0,
NULL,
NULL,
cmd_delete_buffer_exec
};
enum cmd_retval
cmd_delete_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
char *cause;
int buffer;
if (!args_has(args, 'b')) {
paste_free_top(&global_buffers);
return (CMD_RETURN_NORMAL);
}
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
if (cause != NULL) {
cmdq_error(cmdq, "buffer %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
if (paste_free_index(&global_buffers, buffer) != 0) {
cmdq_error(cmdq, "no buffer %d", buffer);
return (CMD_RETURN_ERROR);
}
return (CMD_RETURN_NORMAL);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -18,6 +18,8 @@
#include <sys/types.h>
#include <string.h>
#include "tmux.h"
/*
@ -27,23 +29,46 @@
enum cmd_retval cmd_detach_client_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_detach_client_entry = {
"detach-client", "detach",
"as:t:P", 0, 0,
"[-P] [-a] [-s target-session] " CMD_TARGET_CLIENT_USAGE,
CMD_READONLY,
NULL,
NULL,
cmd_detach_client_exec
.name = "detach-client",
.alias = "detach",
.args = { "as:t:P", 0, 0 },
.usage = "[-P] [-a] [-s target-session] " CMD_TARGET_CLIENT_USAGE,
.sflag = CMD_SESSION,
.tflag = CMD_CLIENT,
.flags = CMD_READONLY,
.exec = cmd_detach_client_exec
};
const struct cmd_entry cmd_suspend_client_entry = {
.name = "suspend-client",
.alias = "suspendc",
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_CLIENT_USAGE,
.tflag = CMD_CLIENT,
.flags = 0,
.exec = cmd_detach_client_exec
};
enum cmd_retval
cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c, *c2;
struct session *s;
enum msgtype msgtype;
u_int i;
struct client *c = cmdq->state.c, *cloop;
struct session *s;
enum msgtype msgtype;
if (self->entry == &cmd_suspend_client_entry) {
tty_stop_tty(&c->tty);
c->flags |= CLIENT_SUSPENDED;
proc_send(c->peer, MSG_SUSPEND, -1, NULL, 0);
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'P'))
msgtype = MSG_DETACHKILL;
@ -51,30 +76,22 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq)
msgtype = MSG_DETACH;
if (args_has(args, 's')) {
s = cmd_find_session(cmdq, args_get(args, 's'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
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);
s = cmdq->state.sflag.s;
TAILQ_FOREACH(cloop, &clients, entry) {
if (cloop->session == s)
server_client_detach(cloop, msgtype);
}
} else {
c = cmd_find_client(cmdq, args_get(args, 't'), 0);
if (c == NULL)
return (CMD_RETURN_ERROR);
if (args_has(args, 'a')) {
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c2 = ARRAY_ITEM(&clients, i);
if (c2 == NULL || c == c2)
continue;
server_write_client(c2, msgtype, NULL, 0);
}
} else
server_write_client(c, msgtype, NULL, 0);
return (CMD_RETURN_STOP);
}
if (args_has(args, 'a')) {
TAILQ_FOREACH(cloop, &clients, entry) {
if (cloop->session != NULL && cloop != c)
server_client_detach(cloop, msgtype);
}
return (CMD_RETURN_NORMAL);
}
server_client_detach(c, msgtype);
return (CMD_RETURN_STOP);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@ -27,79 +27,55 @@
* Displays a message in the status line.
*/
#define DISPLAY_MESSAGE_TEMPLATE \
"[#{session_name}] #{window_index}:" \
"#{window_name}, current pane #{pane_index} " \
"- (%H:%M %d-%b-%y)"
enum cmd_retval cmd_display_message_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_display_message_entry = {
"display-message", "display",
"c:pt:F:", 0, 1,
"[-p] [-c target-client] [-F format] " CMD_TARGET_PANE_USAGE
" [message]",
0,
NULL,
NULL,
cmd_display_message_exec
.name = "display-message",
.alias = "display",
.args = { "c:pt:F:", 0, 1 },
.usage = "[-p] [-c target-client] [-F format] "
CMD_TARGET_PANE_USAGE " [message]",
.cflag = CMD_CLIENT_CANFAIL,
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_display_message_exec
};
enum cmd_retval
cmd_display_message_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
struct session *s;
struct winlink *wl;
struct window_pane *wp;
struct client *c = cmdq->state.c;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl;
struct window_pane *wp = cmdq->state.tflag.wp;
const char *template;
char *msg;
struct format_tree *ft;
char out[BUFSIZ];
time_t t;
size_t len;
if (args_has(args, 't')) {
wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp);
if (wl == NULL)
return (CMD_RETURN_ERROR);
} else {
wl = cmd_find_pane(cmdq, NULL, &s, &wp);
if (wl == NULL)
return (CMD_RETURN_ERROR);
}
if (args_has(args, 'F') && args->argc != 0) {
cmdq_error(cmdq, "only one of -F or argument must be given");
return (CMD_RETURN_ERROR);
}
if (args_has(args, 'c')) {
c = cmd_find_client(cmdq, args_get(args, 'c'), 0);
if (c == NULL)
return (CMD_RETURN_ERROR);
} else {
c = cmd_current_client(cmdq);
if (c == NULL && !args_has(self->args, 'p')) {
cmdq_error(cmdq, "no client available");
return (CMD_RETURN_ERROR);
}
}
template = args_get(args, 'F');
if (args->argc != 0)
template = args->argv[0];
if (template == NULL)
template = DISPLAY_MESSAGE_TEMPLATE;
ft = format_create();
if (c != NULL)
format_client(ft, c);
format_session(ft, s);
format_winlink(ft, s, wl);
format_window_pane(ft, wp);
ft = format_create(cmdq, 0);
format_defaults(ft, c, s, wl, wp);
t = time(NULL);
len = strftime(out, sizeof out, template, localtime(&t));
out[len] = '\0';
msg = format_expand(ft, out);
msg = format_expand_time(ft, template, time(NULL));
if (args_has(self->args, 'p'))
cmdq_print(cmdq, "%s", msg);
else

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@ -27,25 +27,22 @@
enum cmd_retval cmd_display_panes_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_display_panes_entry = {
"display-panes", "displayp",
"t:", 0, 0,
CMD_TARGET_CLIENT_USAGE,
0,
NULL,
NULL,
cmd_display_panes_exec
.name = "display-panes",
.alias = "displayp",
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_CLIENT_USAGE,
.tflag = CMD_CLIENT,
.flags = 0,
.exec = cmd_display_panes_exec
};
enum cmd_retval
cmd_display_panes_exec(struct cmd *self, struct cmd_q *cmdq)
cmd_display_panes_exec(__unused struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
server_set_identify(c);
server_set_identify(cmdq->state.c);
return (CMD_RETURN_NORMAL);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@ -28,6 +28,11 @@
* Find window containing text.
*/
#define FIND_WINDOW_TEMPLATE \
"#{window_index}: #{window_name} " \
"[#{window_width}x#{window_height}] " \
"(#{window_panes} panes) #{window_find_matches}"
enum cmd_retval cmd_find_window_exec(struct cmd *, struct cmd_q *);
void cmd_find_window_callback(struct window_choose_data *);
@ -43,24 +48,28 @@ void cmd_find_window_callback(struct window_choose_data *);
CMD_FIND_WINDOW_BY_NAME)
const struct cmd_entry cmd_find_window_entry = {
"find-window", "findw",
"F:CNt:T", 1, 4,
"[-CNT] [-F format] " CMD_TARGET_WINDOW_USAGE " match-string",
0,
NULL,
NULL,
cmd_find_window_exec
.name = "find-window",
.alias = "findw",
.args = { "F:CNt:T", 1, 4 },
.usage = "[-CNT] [-F format] " CMD_TARGET_WINDOW_USAGE " match-string",
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_find_window_exec
};
struct cmd_find_window_data {
struct winlink *wl;
char *list_ctx;
u_int pane_id;
TAILQ_ENTRY(cmd_find_window_data) entry;
};
ARRAY_DECL(cmd_find_window_data_list, struct cmd_find_window_data);
TAILQ_HEAD(cmd_find_window_list, cmd_find_window_data);
u_int cmd_find_window_match_flags(struct args *);
void cmd_find_window_match(struct cmd_find_window_data_list *, int,
void cmd_find_window_match(struct cmd_find_window_list *, int,
struct winlink *, const char *, const char *);
u_int
@ -84,15 +93,16 @@ cmd_find_window_match_flags(struct args *args)
}
void
cmd_find_window_match(struct cmd_find_window_data_list *find_list,
int match_flags, struct winlink *wl, const char *str, const char *searchstr)
cmd_find_window_match(struct cmd_find_window_list *find_list,
int match_flags, struct winlink *wl, const char *str,
const char *searchstr)
{
struct cmd_find_window_data find_data;
struct cmd_find_window_data *find_data;
struct window_pane *wp;
u_int i, line;
char *sres;
memset(&find_data, 0, sizeof find_data);
find_data = xcalloc(1, sizeof *find_data);
i = 0;
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
@ -100,53 +110,53 @@ cmd_find_window_match(struct cmd_find_window_data_list *find_list,
if ((match_flags & CMD_FIND_WINDOW_BY_NAME) &&
fnmatch(searchstr, wl->window->name, 0) == 0) {
find_data.list_ctx = xstrdup("");
find_data->list_ctx = xstrdup("");
break;
}
if ((match_flags & CMD_FIND_WINDOW_BY_TITLE) &&
fnmatch(searchstr, wp->base.title, 0) == 0) {
xasprintf(&find_data.list_ctx,
xasprintf(&find_data->list_ctx,
"pane %u title: \"%s\"", i - 1, wp->base.title);
break;
}
if (match_flags & CMD_FIND_WINDOW_BY_CONTENT &&
(sres = window_pane_search(wp, str, &line)) != NULL) {
xasprintf(&find_data.list_ctx,
xasprintf(&find_data->list_ctx,
"pane %u line %u: \"%s\"", i - 1, line + 1, sres);
free(sres);
break;
}
}
if (find_data.list_ctx != NULL) {
find_data.wl = wl;
find_data.pane_id = i - 1;
ARRAY_ADD(find_list, find_data);
}
if (find_data->list_ctx != NULL) {
find_data->wl = wl;
find_data->pane_id = i - 1;
TAILQ_INSERT_TAIL(find_list, find_data, entry);
} else
free(find_data);
}
enum cmd_retval
cmd_find_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
struct client *c = cmdq->state.c;
struct window_choose_data *cdata;
struct session *s;
struct winlink *wl, *wm;
struct cmd_find_window_data_list find_list;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl, *wm;
struct cmd_find_window_list find_list;
struct cmd_find_window_data *find_data;
struct cmd_find_window_data *find_data1;
char *str, *searchstr;
const char *template;
u_int i, match_flags;
if ((c = cmd_current_client(cmdq)) == NULL) {
if (c == NULL) {
cmdq_error(cmdq, "no client available");
return (CMD_RETURN_ERROR);
}
s = c->session;
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR);
if ((template = args_get(args, 'F')) == NULL)
template = FIND_WINDOW_TEMPLATE;
@ -154,21 +164,20 @@ cmd_find_window_exec(struct cmd *self, struct cmd_q *cmdq)
match_flags = cmd_find_window_match_flags(args);
str = args->argv[0];
ARRAY_INIT(&find_list);
TAILQ_INIT(&find_list);
xasprintf(&searchstr, "*%s*", str);
RB_FOREACH(wm, winlinks, &s->windows)
cmd_find_window_match (&find_list, match_flags, wm, str, searchstr);
cmd_find_window_match(&find_list, match_flags, wm, str, searchstr);
free(searchstr);
if (ARRAY_LENGTH(&find_list) == 0) {
if (TAILQ_EMPTY(&find_list)) {
cmdq_error(cmdq, "no windows matching: %s", str);
ARRAY_FREE(&find_list);
return (CMD_RETURN_ERROR);
}
if (ARRAY_LENGTH(&find_list) == 1) {
if (session_select(s, ARRAY_FIRST(&find_list).wl->idx) == 0)
if (TAILQ_NEXT(TAILQ_FIRST(&find_list), entry) == NULL) {
if (session_select(s, TAILQ_FIRST(&find_list)->wl->idx) == 0)
server_redraw_session(s);
recalculate_sizes();
goto out;
@ -177,30 +186,33 @@ cmd_find_window_exec(struct cmd *self, struct cmd_q *cmdq)
if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
goto out;
for (i = 0; i < ARRAY_LENGTH(&find_list); i++) {
wm = ARRAY_ITEM(&find_list, i).wl;
i = 0;
TAILQ_FOREACH(find_data, &find_list, entry) {
cdata = window_choose_data_create(TREE_OTHER, c, c->session);
cdata->idx = wm->idx;
cdata->wl = wm;
cdata->idx = find_data->wl->idx;
cdata->wl = find_data->wl;
cdata->ft_template = xstrdup(template);
cdata->pane_id = ARRAY_ITEM(&find_list, i).pane_id;
cdata->pane_id = find_data->pane_id;
format_add(cdata->ft, "line", "%u", i);
format_add(cdata->ft, "window_find_matches", "%s",
ARRAY_ITEM(&find_list, i).list_ctx);
format_session(cdata->ft, s);
format_winlink(cdata->ft, s, wm);
format_window_pane(cdata->ft, wm->window->active);
find_data->list_ctx);
format_defaults(cdata->ft, NULL, s, find_data->wl, NULL);
window_choose_add(wl->window->active, cdata);
i++;
}
window_choose_ready(wl->window->active, 0, cmd_find_window_callback);
out:
ARRAY_FREE(&find_list);
TAILQ_FOREACH_SAFE(find_data, &find_list, entry, find_data1) {
free(find_data->list_ctx);
TAILQ_REMOVE(&find_list, find_data, entry);
free(find_data);
}
return (CMD_RETURN_NORMAL);
}

1228
cmd-find.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,48 +0,0 @@
/* $Id$ */
/*
* 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"
/*
* Cause client to report an error and exit with 1 if session doesn't exist.
*/
enum cmd_retval cmd_has_session_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_has_session_entry = {
"has-session", "has",
"t:", 0, 0,
CMD_TARGET_SESSION_USAGE,
0,
NULL,
NULL,
cmd_has_session_exec
};
enum cmd_retval
cmd_has_session_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
if (cmd_find_session(cmdq, args_get(args, 't'), 0) == NULL)
return (CMD_RETURN_ERROR);
return (CMD_RETURN_NORMAL);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@ -36,21 +36,28 @@ void cmd_if_shell_done(struct cmd_q *);
void cmd_if_shell_free(void *);
const struct cmd_entry cmd_if_shell_entry = {
"if-shell", "if",
"bt:", 2, 3,
"[-b] " CMD_TARGET_PANE_USAGE " shell-command command [command]",
0,
NULL,
NULL,
cmd_if_shell_exec
.name = "if-shell",
.alias = "if",
.args = { "bFt:", 2, 3 },
.usage = "[-bF] " CMD_TARGET_PANE_USAGE " shell-command command "
"[command]",
.tflag = CMD_PANE_CANFAIL,
.flags = 0,
.exec = cmd_if_shell_exec
};
struct cmd_if_shell_data {
char *cmd_if;
char *cmd_else;
struct cmd_q *cmdq;
int bflag;
int started;
char *cmd_if;
char *cmd_else;
struct cmd_q *cmdq;
struct mouse_event mouse;
int bflag;
int references;
};
enum cmd_retval
@ -58,47 +65,65 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct cmd_if_shell_data *cdata;
char *shellcmd;
struct client *c;
struct session *s = NULL;
struct winlink *wl = NULL;
struct window_pane *wp = NULL;
char *shellcmd, *cmd, *cause;
struct cmd_list *cmdlist;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl;
struct window_pane *wp = cmdq->state.tflag.wp;
struct format_tree *ft;
const char *cwd;
if (args_has(args, 't'))
wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp);
else {
c = cmd_find_client(cmdq, NULL, 1);
if (c != NULL && c->session != NULL) {
s = c->session;
wl = s->curw;
wp = wl->window->active;
}
}
cwd = wp->cwd;
ft = format_create();
if (s != NULL)
format_session(ft, s);
if (s != NULL && wl != NULL)
format_winlink(ft, s, wl);
if (wp != NULL)
format_window_pane(ft, wp);
if (cmdq->client != NULL && cmdq->client->session == NULL)
cwd = cmdq->client->cwd;
else if (s != NULL)
cwd = s->cwd;
else
cwd = NULL;
ft = format_create(cmdq, 0);
format_defaults(ft, NULL, s, wl, wp);
shellcmd = format_expand(ft, args->argv[0]);
format_free(ft);
if (args_has(args, 'F')) {
cmd = NULL;
if (*shellcmd != '0' && *shellcmd != '\0')
cmd = args->argv[1];
else if (args->argc == 3)
cmd = args->argv[2];
free(shellcmd);
if (cmd == NULL)
return (CMD_RETURN_NORMAL);
if (cmd_string_parse(cmd, &cmdlist, NULL, 0, &cause) != 0) {
if (cause != NULL) {
cmdq_error(cmdq, "%s", cause);
free(cause);
}
return (CMD_RETURN_ERROR);
}
cmdq_run(cmdq, cmdlist, &cmdq->item->mouse);
cmd_list_free(cmdlist);
return (CMD_RETURN_NORMAL);
}
cdata = xmalloc(sizeof *cdata);
cdata->cmd_if = xstrdup(args->argv[1]);
if (args->argc == 3)
cdata->cmd_else = xstrdup(args->argv[2]);
else
cdata->cmd_else = NULL;
cdata->bflag = args_has(args, 'b');
cdata->started = 0;
cdata->cmdq = cmdq;
memcpy(&cdata->mouse, &cmdq->item->mouse, sizeof cdata->mouse);
cmdq->references++;
job_run(shellcmd, s, cmd_if_shell_callback, cmd_if_shell_free, cdata);
cdata->references = 1;
job_run(shellcmd, s, cwd, cmd_if_shell_callback, cmd_if_shell_free,
cdata);
free(shellcmd);
if (cdata->bflag)
@ -114,7 +139,7 @@ cmd_if_shell_callback(struct job *job)
struct cmd_list *cmdlist;
char *cause, *cmd;
if (cmdq->dead)
if (cmdq->flags & CMD_Q_DEAD)
return;
if (!WIFEXITED(job->status) || WEXITSTATUS(job->status) != 0)
@ -132,13 +157,12 @@ cmd_if_shell_callback(struct job *job)
return;
}
cdata->started = 1;
cmdq1 = cmdq_new(cmdq->client);
cmdq1->emptyfn = cmd_if_shell_done;
cmdq1->data = cdata;
cmdq_run(cmdq1, cmdlist);
cdata->references++;
cmdq_run(cmdq1, cmdlist, &cdata->mouse);
cmd_list_free(cmdlist);
}
@ -148,11 +172,16 @@ cmd_if_shell_done(struct cmd_q *cmdq1)
struct cmd_if_shell_data *cdata = cmdq1->data;
struct cmd_q *cmdq = cdata->cmdq;
if (cmdq1->client_exit >= 0)
cmdq->client_exit = cmdq1->client_exit;
cmdq_free(cmdq1);
if (--cdata->references != 0)
return;
if (!cmdq_free(cmdq) && !cdata->bflag)
cmdq_continue(cmdq);
cmdq_free(cmdq1);
free(cdata->cmd_else);
free(cdata->cmd_if);
free(cdata);
@ -164,7 +193,7 @@ cmd_if_shell_free(void *data)
struct cmd_if_shell_data *cdata = data;
struct cmd_q *cmdq = cdata->cmdq;
if (cdata->started)
if (--cdata->references != 0)
return;
if (!cmdq_free(cmdq) && !cdata->bflag)

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2011 George Nachman <tmux@georgester.com>
@ -28,44 +28,37 @@
* Join or move a pane into another (like split/swap/kill).
*/
void cmd_join_pane_key_binding(struct cmd *, int);
enum cmd_retval cmd_join_pane_exec(struct cmd *, struct cmd_q *);
enum cmd_retval join_pane(struct cmd *, struct cmd_q *, int);
const struct cmd_entry cmd_join_pane_entry = {
"join-pane", "joinp",
"bdhvp:l:s:t:", 0, 0,
"[-bdhv] [-p percentage|-l size] [-s src-pane] [-t dst-pane]",
0,
cmd_join_pane_key_binding,
NULL,
cmd_join_pane_exec
.name = "join-pane",
.alias = "joinp",
.args = { "bdhvp:l:s:t:", 0, 0 },
.usage = "[-bdhv] [-p percentage|-l size] " CMD_SRCDST_PANE_USAGE,
.sflag = CMD_PANE_MARKED,
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_join_pane_exec
};
const struct cmd_entry cmd_move_pane_entry = {
"move-pane", "movep",
"bdhvp:l:s:t:", 0, 0,
"[-bdhv] [-p percentage|-l size] [-s src-pane] [-t dst-pane]",
0,
NULL,
NULL,
cmd_join_pane_exec
};
.name = "move-pane",
.alias = "movep",
void
cmd_join_pane_key_binding(struct cmd *self, int key)
{
switch (key) {
case '%':
self->args = args_create(0);
args_set(self->args, 'h', NULL);
break;
default:
self->args = args_create(0);
break;
}
}
.args = { "bdhvp:l:s:t:", 0, 0 },
.usage = "[-bdhv] [-p percentage|-l size] " CMD_SRCDST_PANE_USAGE,
.sflag = CMD_PANE,
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_join_pane_exec
};
enum cmd_retval
cmd_join_pane_exec(struct cmd *self, struct cmd_q *cmdq)
@ -90,16 +83,15 @@ join_pane(struct cmd *self, struct cmd_q *cmdq, int not_same_window)
enum layout_type type;
struct layout_cell *lc;
dst_wl = cmd_find_pane(cmdq, args_get(args, 't'), &dst_s, &dst_wp);
if (dst_wl == NULL)
return (CMD_RETURN_ERROR);
dst_s = cmdq->state.tflag.s;
dst_wl = cmdq->state.tflag.wl;
dst_wp = cmdq->state.tflag.wp;
dst_w = dst_wl->window;
dst_idx = dst_wl->idx;
server_unzoom_window(dst_w);
src_wl = cmd_find_pane(cmdq, args_get(args, 's'), NULL, &src_wp);
if (src_wl == NULL)
return (CMD_RETURN_ERROR);
src_wl = cmdq->state.sflag.wl;
src_wp = cmdq->state.sflag.wp;
src_w = src_wl->window;
server_unzoom_window(src_w);
@ -144,11 +136,7 @@ join_pane(struct cmd *self, struct cmd_q *cmdq, int not_same_window)
layout_close_pane(src_wp);
if (src_w->active == src_wp) {
src_w->active = TAILQ_PREV(src_wp, window_panes, entry);
if (src_w->active == NULL)
src_w->active = TAILQ_NEXT(src_wp, entry);
}
window_lost_pane(src_w, src_wp);
TAILQ_REMOVE(&src_w->panes, src_wp, entry);
if (window_count_panes(src_w) == 0)

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@ -29,24 +29,24 @@
enum cmd_retval cmd_kill_pane_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_kill_pane_entry = {
"kill-pane", "killp",
"at:", 0, 0,
"[-a] " CMD_TARGET_PANE_USAGE,
0,
NULL,
NULL,
cmd_kill_pane_exec
.name = "kill-pane",
.alias = "killp",
.args = { "at:", 0, 0 },
.usage = "[-a] " CMD_TARGET_PANE_USAGE,
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_kill_pane_exec
};
enum cmd_retval
cmd_kill_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct winlink *wl;
struct window_pane *loopwp, *tmpwp, *wp;
struct winlink *wl = cmdq->state.tflag.wl;
struct window_pane *loopwp, *tmpwp, *wp = cmdq->state.tflag.wp;
if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp)) == NULL)
return (CMD_RETURN_ERROR);
server_unzoom_window(wl->window);
if (window_count_panes(wl->window) == 1) {

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -30,19 +30,32 @@
enum cmd_retval cmd_kill_server_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_kill_server_entry = {
"kill-server", NULL,
"", 0, 0,
"",
0,
NULL,
NULL,
cmd_kill_server_exec
.name = "kill-server",
.alias = NULL,
.args = { "", 0, 0 },
.usage = "",
.flags = 0,
.exec = cmd_kill_server_exec
};
const struct cmd_entry cmd_start_server_entry = {
.name = "start-server",
.alias = "start",
.args = { "", 0, 0 },
.usage = "",
.flags = CMD_STARTSERVER,
.exec = cmd_kill_server_exec
};
enum cmd_retval
cmd_kill_server_exec(unused struct cmd *self, unused struct cmd_q *cmdq)
cmd_kill_server_exec(struct cmd *self, __unused struct cmd_q *cmdq)
{
kill(getpid(), SIGTERM);
if (self->entry == &cmd_kill_server_entry)
kill(getpid(), SIGTERM);
return (CMD_RETURN_NORMAL);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -30,29 +30,38 @@
enum cmd_retval cmd_kill_session_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_kill_session_entry = {
"kill-session", NULL,
"at:", 0, 0,
"[-a] " CMD_TARGET_SESSION_USAGE,
0,
NULL,
NULL,
cmd_kill_session_exec
.name = "kill-session",
.alias = NULL,
.args = { "aCt:", 0, 0 },
.usage = "[-aC] " CMD_TARGET_SESSION_USAGE,
.tflag = CMD_SESSION,
.flags = 0,
.exec = cmd_kill_session_exec
};
enum cmd_retval
cmd_kill_session_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct session *s, *s2, *s3;
struct session *s, *sloop, *stmp;
struct winlink *wl;
if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
s = cmdq->state.tflag.s;
if (args_has(args, 'a')) {
RB_FOREACH_SAFE(s2, sessions, &sessions, s3) {
if (s != s2) {
server_destroy_session(s2);
session_destroy(s2);
if (args_has(args, 'C')) {
RB_FOREACH(wl, winlinks, &s->windows) {
wl->window->flags &= ~WINDOW_ALERTFLAGS;
wl->flags &= ~WINLINK_ALERTFLAGS;
}
server_redraw_session(s);
} else if (args_has(args, 'a')) {
RB_FOREACH_SAFE(sloop, sessions, &sessions, stmp) {
if (sloop != s) {
server_destroy_session(sloop);
session_destroy(sloop);
}
}
} else {

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -27,32 +27,54 @@
enum cmd_retval cmd_kill_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_kill_window_entry = {
"kill-window", "killw",
"at:", 0, 0,
"[-a] " CMD_TARGET_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_kill_window_exec
.name = "kill-window",
.alias = "killw",
.args = { "at:", 0, 0 },
.usage = "[-a] " CMD_TARGET_WINDOW_USAGE,
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_kill_window_exec
};
const struct cmd_entry cmd_unlink_window_entry = {
.name = "unlink-window",
.alias = "unlinkw",
.args = { "kt:", 0, 0 },
.usage = "[-k] " CMD_TARGET_WINDOW_USAGE,
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_kill_window_exec
};
enum cmd_retval
cmd_kill_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct winlink *wl, *wl2, *wl3;
struct session *s;
struct args *args = self->args;
struct winlink *wl = cmdq->state.tflag.wl, *wl2, *wl3;
struct window *w = wl->window;
struct session *s = cmdq->state.tflag.s;
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), &s)) == NULL)
return (CMD_RETURN_ERROR);
if (args_has(args, 'a')) {
RB_FOREACH_SAFE(wl2, winlinks, &s->windows, wl3) {
if (wl != wl2)
server_kill_window(wl2->window);
if (self->entry == &cmd_unlink_window_entry) {
if (!args_has(self->args, 'k') && !session_is_linked(s, w)) {
cmdq_error(cmdq, "window only linked to one session");
return (CMD_RETURN_ERROR);
}
} else
server_kill_window(wl->window);
server_unlink_window(s, wl);
} else {
if (args_has(args, 'a')) {
RB_FOREACH_SAFE(wl2, winlinks, &s->windows, wl3) {
if (wl != wl2)
server_kill_window(wl2->window);
}
} else
server_kill_window(wl->window);
}
recalculate_sizes();
return (CMD_RETURN_NORMAL);

View File

@ -1,70 +0,0 @@
/* $Id$ */
/*
* 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 <stdlib.h>
#include "tmux.h"
/*
* Link a window into another session.
*/
enum cmd_retval cmd_link_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_link_window_entry = {
"link-window", "linkw",
"dks:t:", 0, 0,
"[-dk] " CMD_SRCDST_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_link_window_exec
};
enum cmd_retval
cmd_link_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
#ifdef TMATE
cmdq_error(cmdq, "link window is not supported with tmate");
return (CMD_RETURN_ERROR);
#else
struct args *args = self->args;
struct session *src, *dst;
struct winlink *wl;
char *cause;
int idx, kflag, dflag;
if ((wl = cmd_find_window(cmdq, args_get(args, 's'), &src)) == NULL)
return (CMD_RETURN_ERROR);
if ((idx = cmd_find_index(cmdq, args_get(args, 't'), &dst)) == -2)
return (CMD_RETURN_ERROR);
kflag = args_has(self->args, 'k');
dflag = args_has(self->args, 'd');
if (server_link_window(src, wl, dst, idx, kflag, !dflag, &cause) != 0) {
cmdq_error(cmdq, "can't link window: %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
recalculate_sizes();
return (CMD_RETURN_NORMAL);
#endif
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -27,36 +27,38 @@
* List paste buffers.
*/
#define LIST_BUFFERS_TEMPLATE \
"#{buffer_name}: #{buffer_size} bytes: \"#{buffer_sample}\""
enum cmd_retval cmd_list_buffers_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_list_buffers_entry = {
"list-buffers", "lsb",
"F:", 0, 0,
"[-F format]",
0,
NULL,
NULL,
cmd_list_buffers_exec
.name = "list-buffers",
.alias = "lsb",
.args = { "F:", 0, 0 },
.usage = "[-F format]",
.flags = 0,
.exec = cmd_list_buffers_exec
};
enum cmd_retval
cmd_list_buffers_exec(unused struct cmd *self, struct cmd_q *cmdq)
cmd_list_buffers_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct paste_buffer *pb;
struct format_tree *ft;
u_int idx;
char *line;
const char *template;
if ((template = args_get(args, 'F')) == NULL)
template = LIST_BUFFERS_TEMPLATE;
idx = 0;
while ((pb = paste_walk_stack(&global_buffers, &idx)) != NULL) {
ft = format_create();
format_add(ft, "line", "%u", idx - 1);
format_paste_buffer(ft, pb);
pb = NULL;
while ((pb = paste_walk(pb)) != NULL) {
ft = format_create(cmdq, 0);
format_defaults_paste_buffer(ft, pb);
line = format_expand(ft, template);
cmdq_print(cmdq, "%s", line);

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -28,16 +28,24 @@
* List all clients.
*/
#define LIST_CLIENTS_TEMPLATE \
"#{client_tty}: #{session_name} " \
"[#{client_width}x#{client_height} #{client_termname}]" \
"#{?client_utf8, (utf8),} #{?client_readonly, (ro),}"
enum cmd_retval cmd_list_clients_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_list_clients_entry = {
"list-clients", "lsc",
"F:t:", 0, 0,
"[-F format] " CMD_TARGET_SESSION_USAGE,
CMD_READONLY,
NULL,
NULL,
cmd_list_clients_exec
.name = "list-clients",
.alias = "lsc",
.args = { "F:t:", 0, 0 },
.usage = "[-F format] " CMD_TARGET_SESSION_USAGE,
.tflag = CMD_SESSION,
.flags = CMD_READONLY,
.exec = cmd_list_clients_exec
};
enum cmd_retval
@ -48,37 +56,33 @@ cmd_list_clients_exec(struct cmd *self, struct cmd_q *cmdq)
struct session *s;
struct format_tree *ft;
const char *template;
u_int i;
u_int idx;
char *line;
if (args_has(args, 't')) {
s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
} else
if (args_has(args, 't'))
s = cmdq->state.tflag.s;
else
s = NULL;
if ((template = args_get(args, 'F')) == NULL)
template = LIST_CLIENTS_TEMPLATE;
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session == NULL)
idx = 0;
TAILQ_FOREACH(c, &clients, entry) {
if (c->session == NULL || (s != NULL && s != c->session))
continue;
if (s != NULL && s != c->session)
continue;
ft = format_create();
format_add(ft, "line", "%u", i);
format_session(ft, c->session);
format_client(ft, c);
ft = format_create(cmdq, 0);
format_add(ft, "line", "%u", idx);
format_defaults(ft, c, NULL, NULL, NULL);
line = format_expand(ft, template);
cmdq_print(cmdq, "%s", line);
free(line);
format_free(ft);
idx++;
}
return (CMD_RETURN_NORMAL);

View File

@ -1,55 +0,0 @@
/* $Id$ */
/*
* 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"
/*
* List all commands with usages.
*/
enum cmd_retval cmd_list_commands_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_list_commands_entry = {
"list-commands", "lscm",
"", 0, 0,
"",
0,
NULL,
NULL,
cmd_list_commands_exec
};
enum cmd_retval
cmd_list_commands_exec(unused struct cmd *self, struct cmd_q *cmdq)
{
const struct cmd_entry **entryp;
for (entryp = cmd_table; *entryp != NULL; entryp++) {
if ((*entryp)->alias != NULL) {
cmdq_print(cmdq, "%s (%s) %s", (*entryp)->name,
(*entryp)->alias, (*entryp)->usage);
} else {
cmdq_print(cmdq, "%s %s", (*entryp)->name,
(*entryp)->usage);
}
}
return (CMD_RETURN_NORMAL);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -18,6 +18,7 @@
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
@ -27,27 +28,44 @@
*/
enum cmd_retval cmd_list_keys_exec(struct cmd *, struct cmd_q *);
enum cmd_retval cmd_list_keys_table(struct cmd *, struct cmd_q *);
enum cmd_retval cmd_list_keys_commands(struct cmd_q *);
const struct cmd_entry cmd_list_keys_entry = {
"list-keys", "lsk",
"t:", 0, 0,
"[-t key-table]",
0,
NULL,
NULL,
cmd_list_keys_exec
.name = "list-keys",
.alias = "lsk",
.args = { "t:T:", 0, 0 },
.usage = "[-t mode-table] [-T key-table]",
.flags = CMD_STARTSERVER,
.exec = cmd_list_keys_exec
};
const struct cmd_entry cmd_list_commands_entry = {
.name = "list-commands",
.alias = "lscm",
.args = { "", 0, 0 },
.usage = "",
.flags = CMD_STARTSERVER,
.exec = cmd_list_keys_exec
};
enum cmd_retval
cmd_list_keys_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct key_table *table;
struct key_binding *bd;
const char *key;
char tmp[BUFSIZ], flags[8];
size_t used;
int width, keywidth;
const char *key, *tablename, *r;
char *cp, tmp[BUFSIZ];
int repeat, width, tablewidth, keywidth;
if (self->entry == &cmd_list_commands_entry)
return (cmd_list_keys_commands(cmdq));
#ifdef TMATE
/* XXX TODO Really nasty hack, we really need our own client instance... */
@ -62,46 +80,62 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_q *cmdq)
if (args_has(args, 't'))
return (cmd_list_keys_table(self, cmdq));
width = 0;
RB_FOREACH(bd, key_bindings, &key_bindings) {
key = key_string_lookup_key(bd->key & ~KEYC_PREFIX);
if (key == NULL)
continue;
keywidth = strlen(key);
if (!(bd->key & KEYC_PREFIX)) {
if (bd->can_repeat)
keywidth += 4;
else
keywidth += 3;
} else if (bd->can_repeat)
keywidth += 3;
if (keywidth > width)
width = keywidth;
tablename = args_get(args, 'T');
if (tablename != NULL && key_bindings_get_table(tablename, 0) == NULL) {
cmdq_error(cmdq, "table %s doesn't exist", tablename);
return (CMD_RETURN_ERROR);
}
RB_FOREACH(bd, key_bindings, &key_bindings) {
key = key_string_lookup_key(bd->key & ~KEYC_PREFIX);
if (key == NULL)
repeat = 0;
tablewidth = keywidth = 0;
RB_FOREACH(table, key_tables, &key_tables) {
if (tablename != NULL && strcmp(table->name, tablename) != 0)
continue;
RB_FOREACH(bd, key_bindings, &table->key_bindings) {
key = key_string_lookup_key(bd->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 ");
repeat = 1;
used = xsnprintf(tmp, sizeof tmp, "%s%*s ",
flags, (int) (width - strlen(flags)), key);
if (used >= sizeof tmp)
width = utf8_cstrwidth(table->name);
if (width > tablewidth)
tablewidth = width;
width = utf8_cstrwidth(key);
if (width > keywidth)
keywidth = width;
}
}
RB_FOREACH(table, key_tables, &key_tables) {
if (tablename != NULL && strcmp(table->name, tablename) != 0)
continue;
RB_FOREACH(bd, key_bindings, &table->key_bindings) {
key = key_string_lookup_key(bd->key);
cmd_list_print(bd->cmdlist, tmp + used, (sizeof tmp) - used);
cmdq_print(cmdq, "bind-key %s", tmp);
if (!repeat)
r = "";
else if (bd->can_repeat)
r = "-r ";
else
r = " ";
xsnprintf(tmp, sizeof tmp, "%s-T ", r);
cp = utf8_padcstr(table->name, tablewidth);
strlcat(tmp, cp, sizeof tmp);
strlcat(tmp, " ", sizeof tmp);
free(cp);
cp = utf8_padcstr(key, keywidth);
strlcat(tmp, cp, sizeof tmp);
strlcat(tmp, " ", sizeof tmp);
free(cp);
cp = cmd_list_print(bd->cmdlist);
strlcat(tmp, cp, sizeof tmp);
free(cp);
cmdq_print(cmdq, "bind-key %s", tmp);
}
}
return (CMD_RETURN_NORMAL);
@ -127,8 +161,6 @@ cmd_list_keys_table(struct cmd *self, struct cmd_q *cmdq)
any_mode = 0;
RB_FOREACH(mbind, mode_key_tree, mtab->tree) {
key = key_string_lookup_key(mbind->key);
if (key == NULL)
continue;
if (mbind->mode != 0)
any_mode = 1;
@ -140,8 +172,6 @@ cmd_list_keys_table(struct cmd *self, struct cmd_q *cmdq)
RB_FOREACH(mbind, mode_key_tree, mtab->tree) {
key = key_string_lookup_key(mbind->key);
if (key == NULL)
continue;
mode = "";
if (mbind->mode != 0)
@ -159,3 +189,22 @@ cmd_list_keys_table(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_NORMAL);
}
enum cmd_retval
cmd_list_keys_commands(struct cmd_q *cmdq)
{
const struct cmd_entry **entryp;
const struct cmd_entry *entry;
for (entryp = cmd_table; *entryp != NULL; entryp++) {
entry = *entryp;
if (entry->alias == NULL) {
cmdq_print(cmdq, "%s %s", entry->name, entry->usage);
continue;
}
cmdq_print(cmdq, "%s (%s) %s", entry->name, entry->alias,
entry->usage);
}
return (CMD_RETURN_NORMAL);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@ -19,7 +19,6 @@
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include "tmux.h"
@ -30,41 +29,37 @@
enum cmd_retval cmd_list_panes_exec(struct cmd *, struct cmd_q *);
void cmd_list_panes_server(struct cmd *, struct cmd_q *);
void cmd_list_panes_session(
struct cmd *, struct session *, struct cmd_q *, int);
void cmd_list_panes_window(struct cmd *,
struct session *, struct winlink *, struct cmd_q *, int);
void cmd_list_panes_session(struct cmd *, struct session *, struct cmd_q *,
int);
void cmd_list_panes_window(struct cmd *, struct session *, struct winlink *,
struct cmd_q *, int);
const struct cmd_entry cmd_list_panes_entry = {
"list-panes", "lsp",
"asF:t:", 0, 0,
"[-as] [-F format] " CMD_TARGET_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_list_panes_exec
.name = "list-panes",
.alias = "lsp",
.args = { "asF:t:", 0, 0 },
.usage = "[-as] [-F format] " CMD_TARGET_WINDOW_USAGE,
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_list_panes_exec
};
enum cmd_retval
cmd_list_panes_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct session *s;
struct winlink *wl;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl;
if (args_has(args, 'a'))
cmd_list_panes_server(self, cmdq);
else if (args_has(args, 's')) {
s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
else if (args_has(args, 's'))
cmd_list_panes_session(self, s, cmdq, 1);
} else {
wl = cmd_find_window(cmdq, args_get(args, 't'), &s);
if (wl == NULL)
return (CMD_RETURN_ERROR);
else
cmd_list_panes_window(self, s, wl, cmdq, 0);
}
return (CMD_RETURN_NORMAL);
}
@ -79,8 +74,8 @@ cmd_list_panes_server(struct cmd *self, struct cmd_q *cmdq)
}
void
cmd_list_panes_session(
struct cmd *self, struct session *s, struct cmd_q *cmdq, int type)
cmd_list_panes_session(struct cmd *self, struct session *s, struct cmd_q *cmdq,
int type)
{
struct winlink *wl;
@ -89,8 +84,8 @@ cmd_list_panes_session(
}
void
cmd_list_panes_window(struct cmd *self,
struct session *s, struct winlink *wl, struct cmd_q *cmdq, int type)
cmd_list_panes_window(struct cmd *self, struct session *s, struct winlink *wl,
struct cmd_q *cmdq, int type)
{
struct args *args = self->args;
struct window_pane *wp;
@ -117,9 +112,9 @@ cmd_list_panes_window(struct cmd *self,
"#{?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}, "
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;
@ -128,11 +123,9 @@ cmd_list_panes_window(struct cmd *self,
n = 0;
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
ft = format_create();
ft = format_create(cmdq, 0);
format_add(ft, "line", "%u", n);
format_session(ft, s);
format_winlink(ft, s, wl);
format_window_pane(ft, wp);
format_defaults(ft, NULL, s, wl, wp);
line = format_expand(ft, template);
cmdq_print(cmdq, "%s", line);

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -28,16 +28,25 @@
* List all sessions.
*/
#define LIST_SESSIONS_TEMPLATE \
"#{session_name}: #{session_windows} windows " \
"(created #{t:session_created}) " \
"[#{session_width}x#{session_height}]" \
"#{?session_grouped, (group ,}" \
"#{session_group}#{?session_grouped,),}" \
"#{?session_attached, (attached),}"
enum cmd_retval cmd_list_sessions_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_list_sessions_entry = {
"list-sessions", "ls",
"F:", 0, 0,
"[-F format]",
0,
NULL,
NULL,
cmd_list_sessions_exec
.name = "list-sessions",
.alias = "ls",
.args = { "F:", 0, 0 },
.usage = "[-F format]",
.flags = 0,
.exec = cmd_list_sessions_exec
};
enum cmd_retval
@ -55,9 +64,9 @@ cmd_list_sessions_exec(struct cmd *self, struct cmd_q *cmdq)
n = 0;
RB_FOREACH(s, sessions, &sessions) {
ft = format_create();
ft = format_create(cmdq, 0);
format_add(ft, "line", "%u", n);
format_session(ft, s);
format_defaults(ft, NULL, s, NULL, NULL);
line = format_expand(ft, template);
cmdq_print(cmdq, "%s", line);

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -27,36 +27,46 @@
* List windows on given session.
*/
#define LIST_WINDOWS_TEMPLATE \
"#{window_index}: #{window_name}#{window_flags} " \
"(#{window_panes} panes) " \
"[#{window_width}x#{window_height}] " \
"[layout #{window_layout}] #{window_id}" \
"#{?window_active, (active),}";
#define LIST_WINDOWS_WITH_SESSION_TEMPLATE \
"#{session_name}:" \
"#{window_index}: #{window_name}#{window_flags} " \
"(#{window_panes} panes) " \
"[#{window_width}x#{window_height}] "
enum cmd_retval cmd_list_windows_exec(struct cmd *, struct cmd_q *);
void cmd_list_windows_server(struct cmd *, struct cmd_q *);
void cmd_list_windows_session(
struct cmd *, struct session *, struct cmd_q *, int);
void cmd_list_windows_session(struct cmd *, struct session *,
struct cmd_q *, int);
const struct cmd_entry cmd_list_windows_entry = {
"list-windows", "lsw",
"F:at:", 0, 0,
"[-a] [-F format] " CMD_TARGET_SESSION_USAGE,
0,
NULL,
NULL,
cmd_list_windows_exec
.name = "list-windows",
.alias = "lsw",
.args = { "F:at:", 0, 0 },
.usage = "[-a] [-F format] " CMD_TARGET_SESSION_USAGE,
.tflag = CMD_SESSION,
.flags = 0,
.exec = cmd_list_windows_exec
};
enum cmd_retval
cmd_list_windows_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct session *s;
if (args_has(args, 'a'))
cmd_list_windows_server(self, cmdq);
else {
s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
cmd_list_windows_session(self, s, cmdq, 0);
}
else
cmd_list_windows_session(self, cmdq->state.tflag.s, cmdq, 0);
return (CMD_RETURN_NORMAL);
}
@ -71,8 +81,8 @@ cmd_list_windows_server(struct cmd *self, struct cmd_q *cmdq)
}
void
cmd_list_windows_session(
struct cmd *self, struct session *s, struct cmd_q *cmdq, int type)
cmd_list_windows_session(struct cmd *self, struct session *s,
struct cmd_q *cmdq, int type)
{
struct args *args = self->args;
struct winlink *wl;
@ -95,11 +105,9 @@ cmd_list_windows_session(
n = 0;
RB_FOREACH(wl, winlinks, &s->windows) {
ft = format_create();
ft = format_create(cmdq, 0);
format_add(ft, "line", "%u", n);
format_session(ft, s);
format_winlink(ft, s, wl);
format_window_pane(ft, wl->window->active);
format_defaults(ft, NULL, s, wl, NULL);
line = format_expand(ft, template);
cmdq_print(cmdq, "%s", line);

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@ -24,7 +24,7 @@
#include "tmux.h"
struct cmd_list *
cmd_list_parse(int argc, char **argv, const char* file, u_int line,
cmd_list_parse(int argc, char **argv, const char *file, u_int line,
char **cause)
{
struct cmd_list *cmdlist;
@ -99,21 +99,28 @@ cmd_list_free(struct cmd_list *cmdlist)
free(cmdlist);
}
size_t
cmd_list_print(struct cmd_list *cmdlist, char *buf, size_t len)
char *
cmd_list_print(struct cmd_list *cmdlist)
{
struct cmd *cmd;
size_t off;
char *buf, *this;
size_t len;
len = 1;
buf = xcalloc(1, len);
off = 0;
TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
if (off >= len)
break;
off += cmd_print(cmd, buf + off, len - off);
if (off >= len)
break;
this = cmd_print(cmd);
len += strlen(this) + 3;
buf = xrealloc(buf, len);
strlcat(buf, this, len);
if (TAILQ_NEXT(cmd, qentry) != NULL)
off += xsnprintf(buf + off, len - off, " ; ");
strlcat(buf, " ; ", len);
free(this);
}
return (off);
return (buf);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@ -19,6 +19,7 @@
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -34,13 +35,14 @@ enum cmd_retval cmd_load_buffer_exec(struct cmd *, struct cmd_q *);
void cmd_load_buffer_callback(struct client *, int, void *);
const struct cmd_entry cmd_load_buffer_entry = {
"load-buffer", "loadb",
"b:", 1, 1,
CMD_BUFFER_USAGE " path",
0,
NULL,
NULL,
cmd_load_buffer_exec
.name = "load-buffer",
.alias = "loadb",
.args = { "b:", 1, 1 },
.usage = CMD_BUFFER_USAGE " path",
.flags = 0,
.exec = cmd_load_buffer_exec
};
enum cmd_retval
@ -50,30 +52,19 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
struct client *c = cmdq->client;
struct session *s;
FILE *f;
const char *path, *newpath, *wd;
char *pdata, *new_pdata, *cause;
const char *path, *bufname, *cwd;
char *pdata, *new_pdata, *cause, *file, resolved[PATH_MAX];
size_t psize;
u_int limit;
int ch, error, buffer, *buffer_ptr;
int ch, error;
if (!args_has(args, 'b'))
buffer = -1;
else {
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
if (cause != NULL) {
cmdq_error(cmdq, "buffer %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
}
bufname = NULL;
if (args_has(args, 'b'))
bufname = args_get(args, 'b');
path = args->argv[0];
if (strcmp(path, "-") == 0) {
buffer_ptr = xmalloc(sizeof *buffer_ptr);
*buffer_ptr = buffer;
error = server_set_stdin_callback (c, cmd_load_buffer_callback,
buffer_ptr, &cause);
error = server_set_stdin_callback(c, cmd_load_buffer_callback,
(void *)bufname, &cause);
if (error != 0) {
cmdq_error(cmdq, "%s: %s", path, cause);
free(cause);
@ -82,21 +73,26 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_WAIT);
}
if (c != NULL)
wd = c->cwd;
else if ((s = cmd_current_session(cmdq, 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 (c != NULL && c->session == NULL)
cwd = c->cwd;
else if ((s = c->session) != NULL)
cwd = s->cwd;
else
cwd = ".";
if (*path == '/')
file = xstrdup(path);
else
xasprintf(&file, "%s/%s", cwd, path);
if (realpath(file, resolved) == NULL &&
strlcpy(resolved, file, sizeof resolved) >= sizeof resolved) {
cmdq_error(cmdq, "%s: %s", file, strerror(ENAMETOOLONG));
return (CMD_RETURN_ERROR);
}
if ((f = fopen(path, "rb")) == NULL) {
cmdq_error(cmdq, "%s: %s", path, strerror(errno));
f = fopen(resolved, "rb");
free(file);
if (f == NULL) {
cmdq_error(cmdq, "%s: %s", resolved, strerror(errno));
return (CMD_RETURN_ERROR);
}
@ -112,7 +108,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
pdata[psize++] = ch;
}
if (ferror(f)) {
cmdq_error(cmdq, "%s: read error", path);
cmdq_error(cmdq, "%s: read error", resolved);
goto error;
}
if (pdata != NULL)
@ -120,14 +116,10 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
fclose(f);
limit = options_get_number(&global_options, "buffer-limit");
if (buffer == -1) {
paste_add(&global_buffers, pdata, psize, limit);
return (CMD_RETURN_NORMAL);
}
if (paste_replace(&global_buffers, buffer, pdata, psize) != 0) {
cmdq_error(cmdq, "no buffer %d", buffer);
if (paste_set(pdata, psize, bufname, &cause) != 0) {
cmdq_error(cmdq, "%s", cause);
free(pdata);
free(cause);
return (CMD_RETURN_ERROR);
}
@ -143,39 +135,39 @@ error:
void
cmd_load_buffer_callback(struct client *c, int closed, void *data)
{
int *buffer = data;
char *pdata;
size_t psize;
u_int limit;
const char *bufname = data;
char *pdata, *cause, *saved;
size_t psize;
if (!closed)
return;
c->stdin_callback = NULL;
c->references--;
server_client_unref(c);
if (c->flags & CLIENT_DEAD)
return;
psize = EVBUFFER_LENGTH(c->stdin_data);
if (psize == 0 || (pdata = malloc(psize + 1)) == NULL) {
free(data);
if (psize == 0 || (pdata = malloc(psize + 1)) == NULL)
goto out;
}
memcpy(pdata, EVBUFFER_DATA(c->stdin_data), psize);
pdata[psize] = '\0';
evbuffer_drain(c->stdin_data, psize);
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) {
if (paste_set(pdata, psize, bufname, &cause) != 0) {
/* No context so can't use server_client_msg_error. */
evbuffer_add_printf(c->stderr_data, "no buffer %d\n", *buffer);
server_push_stderr(c);
if (~c->flags & CLIENT_UTF8) {
saved = cause;
cause = utf8_sanitize(saved);
free(saved);
}
evbuffer_add_printf(c->stderr_data, "%s", cause);
server_client_push_stderr(c);
free(pdata);
free(cause);
}
free(data);
out:
cmdq_continue(c->cmdq);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@ -18,10 +18,6 @@
#include <sys/types.h>
#include <pwd.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h"
/*
@ -31,55 +27,52 @@
enum cmd_retval cmd_lock_server_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_lock_server_entry = {
"lock-server", "lock",
"", 0, 0,
"",
0,
NULL,
NULL,
cmd_lock_server_exec
.name = "lock-server",
.alias = "lock",
.args = { "", 0, 0 },
.usage = "",
.flags = 0,
.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,
cmd_lock_server_exec
.name = "lock-session",
.alias = "locks",
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_SESSION_USAGE,
.tflag = CMD_SESSION,
.flags = 0,
.exec = 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
.name = "lock-client",
.alias = "lockc",
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_CLIENT_USAGE,
.tflag = CMD_CLIENT,
.flags = 0,
.exec = cmd_lock_server_exec
};
enum cmd_retval
cmd_lock_server_exec(struct cmd *self, unused struct cmd_q *cmdq)
cmd_lock_server_exec(struct cmd *self, __unused struct cmd_q *cmdq)
{
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) {
s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
server_lock_session(s);
} else {
c = cmd_find_client(cmdq, args_get(args, 't'), 0);
if (c == NULL)
return (CMD_RETURN_ERROR);
server_lock_client(c);
}
else if (self->entry == &cmd_lock_session_entry)
server_lock_session(cmdq->state.tflag.s);
else
server_lock_client(cmdq->state.c);
recalculate_sizes();
return (CMD_RETURN_NORMAL);

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@ -29,13 +29,31 @@
enum cmd_retval cmd_move_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_move_window_entry = {
"move-window", "movew",
"dkrs:t:", 0, 0,
"[-dkr] " CMD_SRCDST_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_move_window_exec
.name = "move-window",
.alias = "movew",
.args = { "adkrs:t:", 0, 0 },
.usage = "[-dkr] " CMD_SRCDST_WINDOW_USAGE,
.sflag = CMD_WINDOW,
.tflag = CMD_MOVEW_R,
.flags = 0,
.exec = cmd_move_window_exec
};
const struct cmd_entry cmd_link_window_entry = {
.name = "link-window",
.alias = "linkw",
.args = { "adks:t:", 0, 0 },
.usage = "[-dk] " CMD_SRCDST_WINDOW_USAGE,
.sflag = CMD_WINDOW,
.tflag = CMD_WINDOW_INDEX,
.flags = 0,
.exec = cmd_move_window_exec
};
enum cmd_retval
@ -46,34 +64,48 @@ cmd_move_window_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_ERROR);
#else
struct args *args = self->args;
struct session *src, *dst, *s;
struct winlink *wl;
struct session *src = cmdq->state.sflag.s;
struct session *dst = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.sflag.wl;
char *cause;
int idx, kflag, dflag;
int idx = cmdq->state.tflag.idx, kflag, dflag, sflag;
kflag = args_has(self->args, 'k');
dflag = args_has(self->args, 'd');
if (args_has(args, 'r')) {
if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
session_renumber_windows(s);
session_renumber_windows(dst);
recalculate_sizes();
return (CMD_RETURN_NORMAL);
}
if ((wl = cmd_find_window(cmdq, args_get(args, 's'), &src)) == NULL)
return (CMD_RETURN_ERROR);
if ((idx = cmd_find_index(cmdq, args_get(args, 't'), &dst)) == -2)
return (CMD_RETURN_ERROR);
kflag = args_has(self->args, 'k');
dflag = args_has(self->args, 'd');
if (server_link_window(src, wl, dst, idx, kflag, !dflag, &cause) != 0) {
cmdq_error(cmdq, "can't move window: %s", cause);
sflag = args_has(self->args, 's');
if (args_has(self->args, 'a')) {
if ((idx = winlink_shuffle_up(dst, dst->curw)) == -1)
return (CMD_RETURN_ERROR);
}
if (server_link_window(src, wl, dst, idx, kflag, !dflag,
&cause) != 0) {
cmdq_error(cmdq, "can't link window: %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
server_unlink_window(src, wl);
if (self->entry == &cmd_move_window_entry)
server_unlink_window(src, wl);
/*
* Renumber the winlinks in the src session only, the destination
* session already has the correct winlink id to us, either
* automatically or specified by -s.
*/
if (!sflag && options_get_number(src->options, "renumber-windows"))
session_renumber_windows(src);
recalculate_sizes();
return (CMD_RETURN_NORMAL);

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -18,7 +18,8 @@
#include <sys/types.h>
#include <pwd.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
@ -30,45 +31,68 @@
* Create a new session and attach to the current terminal unless -d is given.
*/
enum cmd_retval cmd_new_session_check(struct args *);
#define NEW_SESSION_TEMPLATE "#{session_name}:"
enum cmd_retval cmd_new_session_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_new_session_entry = {
"new-session", "new",
"AdDF:n:Ps:t:x:y:", 0, 1,
"[-AdDP] [-F format] [-n window-name] [-s session-name] "
CMD_TARGET_SESSION_USAGE " [-x width] [-y height] [command]",
CMD_STARTSERVER|CMD_CANTNEST|CMD_SENDENVIRON,
NULL,
cmd_new_session_check,
cmd_new_session_exec
.name = "new-session",
.alias = "new",
.args = { "Ac:dDEF:n:Ps:t:x:y:", 0, -1 },
.usage = "[-AdDEP] [-c start-directory] [-F format] [-n window-name] "
"[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] "
"[-y height] [command]",
.tflag = CMD_SESSION_CANFAIL,
.flags = CMD_STARTSERVER,
.exec = cmd_new_session_exec
};
enum cmd_retval
cmd_new_session_check(struct args *args)
{
if (args_has(args, 't') && (args->argc != 0 || args_has(args, 'n')))
return (CMD_RETURN_ERROR);
return (CMD_RETURN_NORMAL);
}
const struct cmd_entry cmd_has_session_entry = {
.name = "has-session",
.alias = "has",
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_SESSION_USAGE,
.tflag = CMD_SESSION,
.flags = 0,
.exec = cmd_new_session_exec
};
enum cmd_retval
cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c = cmdq->client;
struct session *s, *groupwith;
struct session *s, *attach_sess;
struct session *groupwith = cmdq->state.tflag.s;
struct window *w;
struct environ env;
struct environ *env;
struct termios tio, *tiop;
struct passwd *pw;
const char *newname, *target, *update, *cwd, *errstr;
const char *template;
char *cmd, *cause, *cp;
int detached, idx;
const char *newname, *target, *update, *errstr, *template;
const char *path, *cwd, *to_free;
char **argv, *cmd, *cause, *cp;
int detached, already_attached, idx, argc;
u_int sx, sy;
int already_attached;
struct format_tree *ft;
struct environ_entry *envent;
if (self->entry == &cmd_has_session_entry) {
/*
* cmd_prepare() will fail if the session cannot be found,
* hence always return success here.
*/
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 't') && (args->argc != 0 || args_has(args, 'n'))) {
cmdq_error(cmdq, "command or window name given with target");
return (CMD_RETURN_ERROR);
}
newname = args_get(args, 's');
if (newname != NULL) {
@ -76,22 +100,25 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
cmdq_error(cmdq, "bad session name: %s", newname);
return (CMD_RETURN_ERROR);
}
if (session_find(newname) != NULL) {
if ((attach_sess = session_find(newname)) != NULL) {
if (args_has(args, 'A')) {
return (cmd_attach_session(cmdq, newname,
args_has(args, 'D'), 0));
/*
* This cmdq is now destined for
* attach-session. Because attach-session
* will have already been prepared, copy this
* session into its tflag so it can be used.
*/
cmdq->state.tflag.s = attach_sess;
return (cmd_attach_session(cmdq,
args_has(args, 'D'), 0, NULL,
args_has(args, 'E')));
}
cmdq_error(cmdq, "duplicate session: %s", newname);
return (CMD_RETURN_ERROR);
}
}
target = args_get(args, 't');
if (target != NULL) {
groupwith = cmd_find_session(cmdq, target, 0);
if (groupwith == NULL)
return (CMD_RETURN_ERROR);
} else
if ((target = args_get(args, 't')) == NULL)
groupwith = NULL;
/* Set -d if no client. */
@ -104,16 +131,33 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
if (c != NULL && c->session != NULL)
already_attached = 1;
/* Get the new session working directory. */
to_free = NULL;
if (args_has(args, 'c')) {
ft = format_create(cmdq, 0);
format_defaults(ft, c, NULL, NULL, NULL);
to_free = cwd = format_expand(ft, args_get(args, 'c'));
format_free(ft);
} else if (c != NULL && c->session == NULL)
cwd = c->cwd;
else
cwd = ".";
/*
* Save the termios settings, part of which is used for new windows in
* this session.
* If this is a new client, check for nesting and save the termios
* settings (part of which is used for new windows in this session).
*
* This is read again with tcgetattr() rather than using tty.tio as if
* detached, tty_open won't be called. Because of this, it must be done
* before opening the terminal as that calls tcsetattr() to prepare for
* tmux taking over.
* tcgetattr() is used rather than using tty.tio since if the client is
* detached, tty_open won't be called. It must be done before opening
* the terminal as that calls tcsetattr() to prepare for tmux taking
* over.
*/
if (!detached && !already_attached && c->tty.fd != -1) {
if (server_client_check_nested(cmdq->client)) {
cmdq_error(cmdq, "sessions should be nested with care, "
"unset $TMUX to force");
return (CMD_RETURN_ERROR);
}
if (tcgetattr(c->tty.fd, &tio) != 0)
fatal("tcgetattr failed");
tiop = &tio;
@ -122,24 +166,13 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
/* Open the terminal if necessary. */
if (!detached && !already_attached) {
if (server_client_open(c, NULL, &cause) != 0) {
if (server_client_open(c, &cause) != 0) {
cmdq_error(cmdq, "open terminal failed: %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
goto error;
}
}
/* Get the new session working directory. */
if (c != NULL && c->cwd != NULL)
cwd = c->cwd;
else {
pw = getpwuid(getuid());
if (pw->pw_dir != NULL && *pw->pw_dir != '\0')
cwd = pw->pw_dir;
else
cwd = "/";
}
/* Find new session size. */
if (c != NULL) {
sx = c->tty.sx;
@ -152,17 +185,17 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
sx = strtonum(args_get(args, 'x'), 1, USHRT_MAX, &errstr);
if (errstr != NULL) {
cmdq_error(cmdq, "width %s", errstr);
return (CMD_RETURN_ERROR);
goto error;
}
}
if (detached && args_has(args, 'y')) {
sy = strtonum(args_get(args, 'y'), 1, USHRT_MAX, &errstr);
if (errstr != NULL) {
cmdq_error(cmdq, "height %s", errstr);
return (CMD_RETURN_ERROR);
goto error;
}
}
if (sy > 0 && options_get_number(&global_s_options, "status"))
if (sy > 0 && options_get_number(global_s_options, "status"))
sy--;
if (sx == 0)
sx = 1;
@ -170,44 +203,64 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
sy = 1;
/* Figure out the command for the new window. */
if (target != NULL)
cmd = NULL;
else if (args->argc != 0)
cmd = args->argv[0];
argc = -1;
argv = NULL;
if (!args_has(args, 't') && args->argc != 0) {
argc = args->argc;
argv = args->argv;
} else if (target == NULL) {
cmd = options_get_string(global_s_options, "default-command");
if (cmd != NULL && *cmd != '\0') {
argc = 1;
argv = &cmd;
} else {
argc = 0;
argv = NULL;
}
}
path = NULL;
if (c != NULL && c->session == NULL)
envent = environ_find(c->environ, "PATH");
else
cmd = options_get_string(&global_s_options, "default-command");
envent = environ_find(global_environ, "PATH");
if (envent != NULL)
path = envent->value;
/* Construct the environment. */
environ_init(&env);
update = options_get_string(&global_s_options, "update-environment");
if (c != NULL)
environ_update(update, &c->environ, &env);
env = environ_create();
if (c != NULL && !args_has(args, 'E')) {
update = options_get_string(global_s_options,
"update-environment");
environ_update(update, c->environ, env);
}
/* Create the new session. */
idx = -1 - options_get_number(&global_s_options, "base-index");
s = session_create(newname, cmd, cwd, &env, tiop, idx, sx, sy, &cause);
idx = -1 - options_get_number(global_s_options, "base-index");
s = session_create(newname, argc, argv, path, cwd, env, tiop, idx, sx,
sy, &cause);
environ_free(env);
if (s == NULL) {
cmdq_error(cmdq, "create session failed: %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
goto error;
}
environ_free(&env);
/* Set the initial window name if one given. */
if (cmd != NULL && args_has(args, 'n')) {
if (argc >= 0 && args_has(args, 'n')) {
w = s->curw->window;
window_set_name(w, args_get(args, 'n'));
options_set_number(&w->options, "automatic-rename", 0);
options_set_number(w->options, "automatic-rename", 0);
}
/*
* If a target session is given, this is to be part of a session group,
* so add it to the group and synchronize.
*/
if (groupwith != NULL) {
if (args_has(args, 't')) {
session_group_add(groupwith, s);
session_group_synchronize_to(s);
session_select(s, RB_ROOT(&s->windows)->idx);
session_select(s, RB_MIN(winlinks, &s->windows)->idx);
}
/*
@ -215,13 +268,17 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
* taking this session and needs to get MSG_READY and stay around.
*/
if (!detached) {
if (!already_attached)
server_write_ready(c);
else if (c->session != NULL)
if (!already_attached) {
if (~c->flags & CLIENT_CONTROL)
proc_send(c->peer, MSG_READY, -1, NULL, 0);
} else if (c->session != NULL)
c->last_session = c->session;
c->session = s;
server_client_set_key_table(c, NULL);
status_timer_start(c);
notify_attached_session_changed(c);
session_update_activity(s);
session_update_activity(s, NULL);
gettimeofday(&s->last_attached_time, NULL);
server_redraw_client(c);
}
recalculate_sizes();
@ -239,10 +296,8 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
if ((template = args_get(args, 'F')) == NULL)
template = NEW_SESSION_TEMPLATE;
ft = format_create();
if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
format_client(ft, c);
format_session(ft, s);
ft = format_create(cmdq, 0);
format_defaults(ft, c, s, NULL, NULL);
cp = format_expand(ft, template);
cmdq_print(cmdq, "%s", cp);
@ -253,5 +308,13 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
if (!detached)
cmdq->client_exit = 0;
if (to_free != NULL)
free((void *)to_free);
return (CMD_RETURN_NORMAL);
error:
if (to_free != NULL)
free((void *)to_free);
return (CMD_RETURN_ERROR);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -18,7 +18,11 @@
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h"
@ -26,59 +30,79 @@
* Create a new window.
*/
#define NEW_WINDOW_TEMPLATE "#{session_name}:#{window_index}.#{pane_index}"
enum cmd_retval cmd_new_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_new_window_entry = {
"new-window", "neww",
"ac:dF:kn:Pt:", 0, 1,
"[-adkP] [-c start-directory] [-F format] [-n window-name] "
CMD_TARGET_WINDOW_USAGE " [command]",
0,
NULL,
NULL,
cmd_new_window_exec
.name = "new-window",
.alias = "neww",
.args = { "ac:dF:kn:Pt:", 0, -1 },
.usage = "[-adkP] [-c start-directory] [-F format] [-n window-name] "
CMD_TARGET_WINDOW_USAGE " [command]",
.tflag = CMD_WINDOW_INDEX,
.flags = 0,
.exec = cmd_new_window_exec
};
enum cmd_retval
cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct session *s;
struct winlink *wl;
struct client *c;
const char *cmd, *cwd, *template;
char *cause, *cp;
int idx, last, detached;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl;
struct client *c = cmdq->state.c;
int idx = cmdq->state.tflag.idx;
const char *cmd, *path, *template, *cwd, *to_free;
char **argv, *cause, *cp;
int argc, detached;
struct format_tree *ft;
struct environ_entry *envent;
if (args_has(args, 'a')) {
wl = cmd_find_window(cmdq, args_get(args, 't'), &s);
if (wl == NULL)
return (CMD_RETURN_ERROR);
idx = wl->idx + 1;
/* Find the next free index. */
for (last = idx; last < INT_MAX; last++) {
if (winlink_find_by_index(&s->windows, last) == NULL)
break;
}
if (last == INT_MAX) {
if ((idx = winlink_shuffle_up(s, wl)) == -1) {
cmdq_error(cmdq, "no free window indexes");
return (CMD_RETURN_ERROR);
}
/* 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(cmdq, args_get(args, 't'), &s)) == -2)
return (CMD_RETURN_ERROR);
}
detached = args_has(args, 'd');
if (args->argc == 0) {
cmd = options_get_string(s->options, "default-command");
if (cmd != NULL && *cmd != '\0') {
argc = 1;
argv = (char **)&cmd;
} else {
argc = 0;
argv = NULL;
}
} else {
argc = args->argc;
argv = args->argv;
}
path = NULL;
if (cmdq->client != NULL && cmdq->client->session == NULL)
envent = environ_find(cmdq->client->environ, "PATH");
else
envent = environ_find(s->environ, "PATH");
if (envent != NULL)
path = envent->value;
to_free = NULL;
if (args_has(args, 'c')) {
ft = format_create(cmdq, 0);
format_defaults(ft, c, s, NULL, NULL);
cwd = to_free = format_expand(ft, args_get(args, 'c'));
format_free(ft);
} else if (cmdq->client != NULL && cmdq->client->session == NULL)
cwd = cmdq->client->cwd;
else
cwd = s->cwd;
wl = NULL;
if (idx != -1)
wl = winlink_find_by_index(&s->windows, idx);
@ -99,19 +123,14 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
}
}
if (args->argc == 0)
cmd = options_get_string(&s->options, "default-command");
else
cmd = args->argv[0];
cwd = cmd_get_default_path(cmdq, args_get(args, 'c'));
if (idx == -1)
idx = -1 - options_get_number(&s->options, "base-index");
wl = session_new(s, args_get(args, 'n'), cmd, cwd, idx, &cause);
idx = -1 - options_get_number(s->options, "base-index");
wl = session_new(s, args_get(args, 'n'), argc, argv, path, cwd, idx,
&cause);
if (wl == NULL) {
cmdq_error(cmdq, "create window failed: %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
goto error;
}
if (!detached) {
session_select(s, wl->idx);
@ -123,12 +142,8 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
if ((template = args_get(args, 'F')) == NULL)
template = NEW_WINDOW_TEMPLATE;
ft = format_create();
if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
format_client(ft, c);
format_session(ft, s);
format_winlink(ft, s, wl);
format_window_pane(ft, wl->window->active);
ft = format_create(cmdq, 0);
format_defaults(ft, c, s, wl, NULL);
cp = format_expand(ft, template);
cmdq_print(cmdq, "%s", cp);
@ -137,5 +152,12 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
format_free(ft);
}
if (to_free != NULL)
free((void *)to_free);
return (CMD_RETURN_NORMAL);
error:
if (to_free != NULL)
free((void *)to_free);
return (CMD_RETURN_ERROR);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -33,52 +33,44 @@ void cmd_paste_buffer_filter(struct window_pane *,
const char *, size_t, const char *, int);
const struct cmd_entry cmd_paste_buffer_entry = {
"paste-buffer", "pasteb",
"db:prs:t:", 0, 0,
"[-dpr] [-s separator] [-b buffer-index] " CMD_TARGET_PANE_USAGE,
0,
NULL,
NULL,
cmd_paste_buffer_exec
.name = "paste-buffer",
.alias = "pasteb",
.args = { "db:prs:t:", 0, 0 },
.usage = "[-dpr] [-s separator] " CMD_BUFFER_USAGE " "
CMD_TARGET_PANE_USAGE,
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_paste_buffer_exec
};
enum cmd_retval
cmd_paste_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct window_pane *wp;
struct session *s;
struct window_pane *wp = cmdq->state.tflag.wp;
struct paste_buffer *pb;
const char *sepstr;
char *cause;
int buffer;
int pflag;
const char *sepstr, *bufname, *bufdata, *bufend, *line;
size_t seplen, bufsize;
int bracket = args_has(args, 'p');
if (cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp) == NULL)
return (CMD_RETURN_ERROR);
bufname = NULL;
if (args_has(args, 'b'))
bufname = args_get(args, 'b');
if (!args_has(args, 'b'))
buffer = -1;
if (bufname == NULL)
pb = paste_get_top(NULL);
else {
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
if (cause != NULL) {
cmdq_error(cmdq, "buffer %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
}
if (buffer == -1)
pb = paste_get_top(&global_buffers);
else {
pb = paste_get_index(&global_buffers, buffer);
pb = paste_get_name(bufname);
if (pb == NULL) {
cmdq_error(cmdq, "no buffer %d", buffer);
cmdq_error(cmdq, "no buffer %s", bufname);
return (CMD_RETURN_ERROR);
}
}
if (pb != NULL) {
if (pb != NULL && ~wp->flags & PANE_INPUTOFF) {
sepstr = args_get(args, 's');
if (sepstr == NULL) {
if (args_has(args, 'r'))
@ -86,17 +78,33 @@ cmd_paste_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
else
sepstr = "\r";
}
pflag = (wp->screen->mode & MODE_BRACKETPASTE);
paste_send_pane(pb, wp, sepstr, args_has(args, 'p') && pflag);
seplen = strlen(sepstr);
if (bracket && (wp->screen->mode & MODE_BRACKETPASTE))
bufferevent_write(wp->event, "\033[200~", 6);
bufdata = paste_buffer_data(pb, &bufsize);
bufend = bufdata + bufsize;
for (;;) {
line = memchr(bufdata, '\n', bufend - bufdata);
if (line == NULL)
break;
bufferevent_write(wp->event, bufdata, line - bufdata);
bufferevent_write(wp->event, sepstr, seplen);
bufdata = line + 1;
}
if (bufdata != bufend)
bufferevent_write(wp->event, bufdata, bufend - bufdata);
if (bracket && (wp->screen->mode & MODE_BRACKETPASTE))
bufferevent_write(wp->event, "\033[201~", 6);
}
/* Delete the buffer if -d. */
if (args_has(args, 'd')) {
if (buffer == -1)
paste_free_top(&global_buffers);
else
paste_free_index(&global_buffers, buffer);
}
if (pb != NULL && args_has(args, 'd'))
paste_free(pb);
return (CMD_RETURN_NORMAL);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@ -21,6 +21,7 @@
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
@ -36,27 +37,29 @@ enum cmd_retval cmd_pipe_pane_exec(struct cmd *, struct cmd_q *);
void cmd_pipe_pane_error_callback(struct bufferevent *, short, void *);
const struct cmd_entry cmd_pipe_pane_entry = {
"pipe-pane", "pipep",
"ot:", 0, 1,
"[-o] " CMD_TARGET_PANE_USAGE " [command]",
0,
NULL,
NULL,
cmd_pipe_pane_exec
.name = "pipe-pane",
.alias = "pipep",
.args = { "ot:", 0, 1 },
.usage = "[-o] " CMD_TARGET_PANE_USAGE " [command]",
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_pipe_pane_exec
};
enum cmd_retval
cmd_pipe_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
struct window_pane *wp;
char *command;
struct client *c = cmdq->state.c;
struct window_pane *wp = cmdq->state.tflag.wp;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl;
char *cmd;
int old_fd, pipe_fd[2], null_fd;
if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL)
return (CMD_RETURN_ERROR);
c = cmd_find_client(cmdq, NULL, 1);
struct format_tree *ft;
/* Destroy the old pipe. */
old_fd = wp->pipe_fd;
@ -85,10 +88,18 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_ERROR);
}
/* Expand the command. */
ft = format_create(cmdq, 0);
format_defaults(ft, c, s, wl, wp);
cmd = format_expand_time(ft, args->argv[0], time(NULL));
format_free(ft);
/* Fork the child. */
switch (fork()) {
case -1:
cmdq_error(cmdq, "fork error: %s", strerror(errno));
free(cmd);
return (CMD_RETURN_ERROR);
case 0:
/* Child process. */
@ -110,9 +121,7 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_q *cmdq)
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);
execl(_PATH_BSHELL, "sh", "-c", cmd, (char *) NULL);
_exit(1);
default:
/* Parent process. */
@ -126,13 +135,15 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmd_q *cmdq)
bufferevent_enable(wp->pipe_event, EV_WRITE);
setblocking(wp->pipe_fd, 0);
free(cmd);
return (CMD_RETURN_NORMAL);
}
}
void
cmd_pipe_pane_error_callback(
unused struct bufferevent *bufev, unused short what, void *data)
cmd_pipe_pane_error_callback(__unused struct bufferevent *bufev,
__unused short what, void *data)
{
struct window_pane *wp = data;

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2013 Nicholas Marriott <nicm@users.sourceforge.net>
@ -20,11 +20,14 @@
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "tmux.h"
#include "tmate.h"
static enum cmd_retval cmdq_continue_one(struct cmd_q *);
/* Create new command queue. */
struct cmd_q *
cmdq_new(struct client *c)
@ -33,15 +36,18 @@ cmdq_new(struct client *c)
cmdq = xcalloc(1, sizeof *cmdq);
cmdq->references = 1;
cmdq->dead = 0;
cmdq->flags = 0;
cmdq->client = c;
cmdq->client_exit = 0;
cmdq->client_exit = -1;
TAILQ_INIT(&cmdq->queue);
cmdq->item = NULL;
cmdq->cmd = NULL;
cmd_find_clear_state(&cmdq->current, NULL, 0);
cmdq->parent = NULL;
return (cmdq);
}
@ -49,8 +55,11 @@ cmdq_new(struct client *c)
int
cmdq_free(struct cmd_q *cmdq)
{
if (--cmdq->references != 0)
return (cmdq->dead);
if (--cmdq->references != 0) {
if (cmdq->flags & CMD_Q_DEAD)
return (1);
return (0);
}
cmdq_flush(cmdq);
free(cmdq);
@ -58,31 +67,38 @@ cmdq_free(struct cmd_q *cmdq)
}
/* Show message from command. */
void printflike2
void
cmdq_print(struct cmd_q *cmdq, const char *fmt, ...)
{
struct client *c = cmdq->client;
struct window *w;
va_list ap;
char *tmp, *msg;
va_start(ap, fmt);
if (c == NULL)
/* nothing */;
else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
va_start(ap, fmt);
evbuffer_add_vprintf(c->stdout_data, fmt, ap);
va_end(ap);
if (~c->flags & CLIENT_UTF8) {
vasprintf(&tmp, fmt, ap);
msg = utf8_sanitize(tmp);
free(tmp);
evbuffer_add(c->stdout_data, msg, strlen(msg));
free(msg);
} else
evbuffer_add_vprintf(c->stdout_data, fmt, ap);
evbuffer_add(c->stdout_data, "\n", 1);
server_push_stdout(c);
server_client_push_stdout(c);
} else {
w = c->session->curw->window;
if (w->active->mode != &window_copy_mode) {
window_pane_reset_mode(w->active);
window_pane_set_mode(w->active, &window_copy_mode);
window_copy_init_for_output(w->active);
#ifdef TMATE
tmate_sync_copy_mode(w->active);
#endif
}
window_copy_vadd(w->active, fmt, ap);
}
@ -90,69 +106,41 @@ cmdq_print(struct cmd_q *cmdq, const char *fmt, ...)
va_end(ap);
}
/* Show info from command. */
void printflike2
cmdq_info(struct cmd_q *cmdq, const char *fmt, ...)
{
struct client *c = cmdq->client;
va_list ap;
char *msg;
if (options_get_number(&global_options, "quiet"))
return;
va_start(ap, fmt);
if (c == NULL)
/* nothing */;
else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
va_start(ap, fmt);
evbuffer_add_vprintf(c->stdout_data, fmt, ap);
va_end(ap);
evbuffer_add(c->stdout_data, "\n", 1);
server_push_stdout(c);
} else {
xvasprintf(&msg, fmt, ap);
*msg = toupper((u_char) *msg);
status_message_set(c, "%s", msg);
free(msg);
}
va_end(ap);
}
/* Show error from command. */
void printflike2
void
cmdq_error(struct cmd_q *cmdq, const char *fmt, ...)
{
struct client *c = cmdq->client;
struct cmd *cmd = cmdq->cmd;
va_list ap;
char *msg, *cause;
char *msg;
size_t msglen;
char *tmp;
va_start(ap, fmt);
msglen = xvasprintf(&msg, fmt, ap);
va_end(ap);
if (c == NULL) {
if (c == NULL)
#ifdef TMATE
if (cmd->file && cmd->line)
xasprintf(&cause, "%s:%u: %s", cmd->file, cmd->line, msg);
cfg_add_cause("%s:%u: %s", cmd->file, cmd->line, msg);
else
xasprintf(&cause, "%s", msg);
cfg_add_cause("%s", msg);
#else
xasprintf(&cause, "%s:%u: %s", cmd->file, cmd->line, msg);
cfg_add_cause("%s:%u: %s", cmd->file, cmd->line, msg);
#endif
ARRAY_ADD(&cfg_causes, cause);
} else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
else if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
if (~c->flags & CLIENT_UTF8) {
tmp = msg;
msg = utf8_sanitize(tmp);
free(tmp);
msglen = strlen(msg);
}
evbuffer_add(c->stderr_data, msg, msglen);
evbuffer_add(c->stderr_data, "\n", 1);
server_push_stderr(c);
c->retcode = 1;
server_client_push_stderr(c);
c->retval = 1;
} else {
*msg = toupper((u_char) *msg);
status_message_set(c, "%s", msg);
@ -162,27 +150,24 @@ cmdq_error(struct cmd_q *cmdq, const char *fmt, ...)
}
/* Print a guard line. */
int
cmdq_guard(struct cmd_q *cmdq, const char *guard)
void
cmdq_guard(struct cmd_q *cmdq, const char *guard, int flags)
{
struct client *c = cmdq->client;
if (c == NULL || c->session == NULL)
return 0;
if (!(c->flags & CLIENT_CONTROL))
return 0;
if (c == NULL || !(c->flags & CLIENT_CONTROL))
return;
evbuffer_add_printf(c->stdout_data, "%%%s %ld %u\n", guard,
(long) cmdq->time, cmdq->number);
server_push_stdout(c);
return 1;
evbuffer_add_printf(c->stdout_data, "%%%s %ld %u %d\n", guard,
(long) cmdq->time, cmdq->number, flags);
server_client_push_stdout(c);
}
/* Add command list to queue and begin processing if needed. */
void
cmdq_run(struct cmd_q *cmdq, struct cmd_list *cmdlist)
cmdq_run(struct cmd_q *cmdq, struct cmd_list *cmdlist, struct mouse_event *m)
{
cmdq_append(cmdq, cmdlist);
cmdq_append(cmdq, cmdlist, m);
if (cmdq->item == NULL) {
cmdq->cmd = NULL;
@ -192,7 +177,7 @@ cmdq_run(struct cmd_q *cmdq, struct cmd_list *cmdlist)
/* Add command list to queue. */
void
cmdq_append(struct cmd_q *cmdq, struct cmd_list *cmdlist)
cmdq_append(struct cmd_q *cmdq, struct cmd_list *cmdlist, struct mouse_event *m)
{
struct cmd_q_item *item;
@ -200,19 +185,64 @@ cmdq_append(struct cmd_q *cmdq, struct cmd_list *cmdlist)
item->cmdlist = cmdlist;
TAILQ_INSERT_TAIL(&cmdq->queue, item, qentry);
cmdlist->references++;
if (m != NULL)
memcpy(&item->mouse, m, sizeof item->mouse);
else
item->mouse.valid = 0;
}
/* Process one command. */
static enum cmd_retval
cmdq_continue_one(struct cmd_q *cmdq)
{
struct cmd *cmd = cmdq->cmd;
enum cmd_retval retval;
char *tmp;
int flags = !!(cmd->flags & CMD_CONTROL);
tmp = cmd_print(cmd);
log_debug("cmdq %p: %s", cmdq, tmp);
#ifdef TMATE
if (tmate_should_replicate_cmd(cmd->entry))
tmate_exec_cmd(tmp);
#endif
free(tmp);
cmdq->time = time(NULL);
cmdq->number++;
cmdq_guard(cmdq, "begin", flags);
if (cmd_prepare_state(cmd, cmdq) != 0)
goto error;
retval = cmd->entry->exec(cmd, cmdq);
if (retval == CMD_RETURN_ERROR)
goto error;
cmdq_guard(cmdq, "end", flags);
return (retval);
error:
cmdq_guard(cmdq, "error", flags);
return (CMD_RETURN_ERROR);
}
/* Continue processing command queue. Returns 1 if finishes empty. */
int
cmdq_continue(struct cmd_q *cmdq)
{
struct client *c = cmdq->client;
struct cmd_q_item *next;
enum cmd_retval retval;
int empty, guard;
char s[1024];
int empty;
cmdq->references++;
notify_disable();
log_debug("continuing cmdq %p: flags %#x, client %p", cmdq, cmdq->flags,
c);
empty = TAILQ_EMPTY(&cmdq->queue);
if (empty)
goto empty;
@ -224,30 +254,8 @@ cmdq_continue(struct cmd_q *cmdq)
cmdq->cmd = TAILQ_NEXT(cmdq->cmd, qentry);
do {
next = TAILQ_NEXT(cmdq->item, qentry);
while (cmdq->cmd != NULL) {
cmd_print(cmdq->cmd, s, sizeof s);
log_debug("cmdq %p: %s (client %d)", cmdq, s,
cmdq->client != NULL ? cmdq->client->ibuf.fd : -1);
cmdq->time = time(NULL);
cmdq->number++;
#ifdef TMATE
if (tmate_should_replicate_cmd(cmdq->cmd->entry))
tmate_exec_cmd(s);
#endif
guard = cmdq_guard(cmdq, "begin");
retval = cmdq->cmd->entry->exec(cmdq->cmd, cmdq);
if (guard) {
if (retval == CMD_RETURN_ERROR)
cmdq_guard(cmdq, "error");
else
cmdq_guard(cmdq, "end");
}
retval = cmdq_continue_one(cmdq);
if (retval == CMD_RETURN_ERROR)
break;
if (retval == CMD_RETURN_WAIT)
@ -256,9 +264,9 @@ cmdq_continue(struct cmd_q *cmdq)
cmdq_flush(cmdq);
goto empty;
}
cmdq->cmd = TAILQ_NEXT(cmdq->cmd, qentry);
}
next = TAILQ_NEXT(cmdq->item, qentry);
TAILQ_REMOVE(&cmdq->queue, cmdq->item, qentry);
cmd_list_free(cmdq->item->cmdlist);
@ -270,14 +278,16 @@ cmdq_continue(struct cmd_q *cmdq)
} while (cmdq->item != NULL);
empty:
if (cmdq->client_exit)
if (cmdq->client_exit > 0)
cmdq->client->flags |= CLIENT_EXIT;
if (cmdq->emptyfn != NULL)
cmdq->emptyfn(cmdq); /* may free cmdq */
cmdq->emptyfn(cmdq);
empty = 1;
out:
notify_enable();
cmdq_free(cmdq);
return (empty);
}
@ -294,3 +304,4 @@ cmdq_flush(struct cmd_q *cmdq)
}
cmdq->item = NULL;
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -27,26 +27,26 @@
enum cmd_retval cmd_refresh_client_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_refresh_client_entry = {
"refresh-client", "refresh",
"C:St:", 0, 0,
"[-S] [-C size]" CMD_TARGET_CLIENT_USAGE,
0,
NULL,
NULL,
cmd_refresh_client_exec
.name = "refresh-client",
.alias = "refresh",
.args = { "C:St:", 0, 0 },
.usage = "[-S] [-C size] " CMD_TARGET_CLIENT_USAGE,
.tflag = CMD_CLIENT,
.flags = 0,
.exec = cmd_refresh_client_exec
};
enum cmd_retval
cmd_refresh_client_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
struct client *c = cmdq->state.c;
const char *size;
u_int w, h;
if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
if (args_has(args, 'C')) {
if ((size = args_get(args, 'C')) == NULL) {
cmdq_error(cmdq, "missing size");
@ -68,10 +68,12 @@ cmd_refresh_client_exec(struct cmd *self, struct cmd_q *cmdq)
if (tty_set_size(&c->tty, w, h))
recalculate_sizes();
} else if (args_has(args, 'S')) {
status_update_jobs(c);
c->flags |= CLIENT_STATUSFORCE;
server_status_client(c);
} else
} else {
c->flags |= CLIENT_STATUSFORCE;
server_redraw_client(c);
}
return (CMD_RETURN_NORMAL);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -29,20 +29,23 @@
enum cmd_retval cmd_rename_session_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_rename_session_entry = {
"rename-session", "rename",
"t:", 1, 1,
CMD_TARGET_SESSION_USAGE " new-name",
0,
NULL,
NULL,
cmd_rename_session_exec
.name = "rename-session",
.alias = "rename",
.args = { "t:", 1, 1 },
.usage = CMD_TARGET_SESSION_USAGE " new-name",
.tflag = CMD_SESSION,
.flags = 0,
.exec = cmd_rename_session_exec
};
enum cmd_retval
cmd_rename_session_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct session *s;
struct session *s = cmdq->state.tflag.s;
const char *newname;
newname = args->argv[0];
@ -55,9 +58,6 @@ cmd_rename_session_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_ERROR);
}
if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
RB_REMOVE(sessions, &sessions, s);
free(s->name);
s->name = xstrdup(newname);

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -29,27 +29,26 @@
enum cmd_retval cmd_rename_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_rename_window_entry = {
"rename-window", "renamew",
"t:", 1, 1,
CMD_TARGET_WINDOW_USAGE " new-name",
0,
NULL,
NULL,
cmd_rename_window_exec
.name = "rename-window",
.alias = "renamew",
.args = { "t:", 1, 1 },
.usage = CMD_TARGET_WINDOW_USAGE " new-name",
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_rename_window_exec
};
enum cmd_retval
cmd_rename_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct session *s;
struct winlink *wl;
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), &s)) == NULL)
return (CMD_RETURN_ERROR);
struct winlink *wl = cmdq->state.tflag.wl;
window_set_name(wl->window, args->argv[0]);
options_set_number(&wl->window->options, "automatic-rename", 0);
options_set_number(wl->window->options, "automatic-rename", 0);
server_status_window(wl->window);

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@ -26,81 +26,49 @@
* Increase or decrease pane size.
*/
void cmd_resize_pane_key_binding(struct cmd *, int);
enum cmd_retval cmd_resize_pane_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_resize_pane_entry = {
"resize-pane", "resizep",
"DLRt:Ux:y:Z", 0, 1,
"[-DLRUZ] [-x width] [-y height] " CMD_TARGET_PANE_USAGE " [adjustment]",
0,
cmd_resize_pane_key_binding,
NULL,
cmd_resize_pane_exec
};
void cmd_resize_pane_mouse_update(struct client *, struct mouse_event *);
void
cmd_resize_pane_key_binding(struct cmd *self, int key)
{
switch (key) {
case KEYC_UP | KEYC_CTRL:
self->args = args_create(0);
args_set(self->args, 'U', NULL);
break;
case KEYC_DOWN | KEYC_CTRL:
self->args = args_create(0);
args_set(self->args, 'D', NULL);
break;
case KEYC_LEFT | KEYC_CTRL:
self->args = args_create(0);
args_set(self->args, 'L', NULL);
break;
case KEYC_RIGHT | KEYC_CTRL:
self->args = args_create(0);
args_set(self->args, 'R', NULL);
break;
case KEYC_UP | KEYC_ESCAPE:
self->args = args_create(1, "5");
args_set(self->args, 'U', NULL);
break;
case KEYC_DOWN | KEYC_ESCAPE:
self->args = args_create(1, "5");
args_set(self->args, 'D', NULL);
break;
case KEYC_LEFT | KEYC_ESCAPE:
self->args = args_create(1, "5");
args_set(self->args, 'L', NULL);
break;
case KEYC_RIGHT | KEYC_ESCAPE:
self->args = args_create(1, "5");
args_set(self->args, 'R', NULL);
break;
case 'z':
self->args = args_create(0);
args_set(self->args, 'Z', NULL);
break;
default:
self->args = args_create(0);
break;
}
}
const struct cmd_entry cmd_resize_pane_entry = {
.name = "resize-pane",
.alias = "resizep",
.args = { "DLMRt:Ux:y:Z", 0, 1 },
.usage = "[-DLMRUZ] [-x width] [-y height] " CMD_TARGET_PANE_USAGE " "
"[adjustment]",
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_resize_pane_exec
};
enum cmd_retval
cmd_resize_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct winlink *wl;
struct window *w;
struct window_pane *wp = cmdq->state.tflag.wp;
struct winlink *wl = cmdq->state.tflag.wl;
struct window *w = wl->window;
struct client *c = cmdq->client;
struct session *s = cmdq->state.tflag.s;
const char *errstr;
char *cause;
struct window_pane *wp;
u_int adjust;
int x, y;
if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp)) == NULL)
return (CMD_RETURN_ERROR);
w = wl->window;
if (args_has(args, 'M')) {
if (cmd_mouse_window(&cmdq->item->mouse, &s) == NULL)
return (CMD_RETURN_NORMAL);
if (c == NULL || c->session != s)
return (CMD_RETURN_NORMAL);
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update;
cmd_resize_pane_mouse_update(c, &cmdq->item->mouse);
return (CMD_RETURN_NORMAL);
}
w = wl->window;
if (args_has(args, 'Z')) {
if (w->flags & WINDOW_ZOOMED)
window_unzoom(w);
@ -155,3 +123,50 @@ cmd_resize_pane_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_NORMAL);
}
void
cmd_resize_pane_mouse_update(struct client *c, struct mouse_event *m)
{
struct winlink *wl;
struct window_pane *wp;
int found;
u_int y, ly;
wl = cmd_mouse_window(m, NULL);
if (wl == NULL) {
c->tty.mouse_drag_update = NULL;
return;
}
y = m->y;
if (m->statusat == 0 && y > 0)
y--;
else if (m->statusat > 0 && y >= (u_int)m->statusat)
y = m->statusat - 1;
ly = m->ly;
if (m->statusat == 0 && ly > 0)
ly--;
else if (m->statusat > 0 && ly >= (u_int)m->statusat)
ly = m->statusat - 1;
found = 0;
TAILQ_FOREACH(wp, &wl->window->panes, entry) {
if (!window_pane_visible(wp))
continue;
if (wp->xoff + wp->sx == m->lx &&
wp->yoff <= 1 + ly && wp->yoff + wp->sy >= ly) {
layout_resize_pane(wp, LAYOUT_LEFTRIGHT, m->x - m->lx);
found = 1;
}
if (wp->yoff + wp->sy == ly &&
wp->xoff <= 1 + m->lx && wp->xoff + wp->sx >= m->lx) {
layout_resize_pane(wp, LAYOUT_TOPBOTTOM, y - ly);
found = 1;
}
}
if (found)
server_redraw_window(wl->window);
else
c->tty.mouse_drag_update = NULL;
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@ -31,62 +31,67 @@
enum cmd_retval cmd_respawn_pane_exec(struct cmd *, struct cmd_q *);
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
.name = "respawn-pane",
.alias = "respawnp",
.args = { "kt:", 0, -1 },
.usage = "[-k] " CMD_TARGET_PANE_USAGE " [command]",
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_respawn_pane_exec
};
enum cmd_retval
cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct winlink *wl;
struct window *w;
struct window_pane *wp;
struct session *s;
struct environ env;
const char *cmd;
struct winlink *wl = cmdq->state.tflag.wl;
struct window *w = wl->window;
struct window_pane *wp = cmdq->state.tflag.wp;
struct session *s = cmdq->state.tflag.s;
struct environ *env;
const char *path;
char *cause;
u_int idx;
if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL)
return (CMD_RETURN_ERROR);
w = wl->window;
struct environ_entry *envent;
if (!args_has(self->args, 'k') && wp->fd != -1) {
if (window_pane_index(wp, &idx) != 0)
fatalx("index not found");
cmdq_error(cmdq, "pane still active: %s:%u.%u",
cmdq_error(cmdq, "pane still active: %s:%d.%u",
s->name, wl->idx, idx);
return (CMD_RETURN_ERROR);
}
environ_init(&env);
environ_copy(&global_environ, &env);
environ_copy(&s->environ, &env);
server_fill_environ(s, &env);
env = environ_create();
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];
path = NULL;
if (cmdq->client != NULL && cmdq->client->session == NULL)
envent = environ_find(cmdq->client->environ, "PATH");
else
cmd = NULL;
if (window_pane_spawn(wp, cmd, NULL, NULL, &env, s->tio, &cause) != 0) {
envent = environ_find(s->environ, "PATH");
if (envent != NULL)
path = envent->value;
if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, NULL, env,
s->tio, &cause) != 0) {
cmdq_error(cmdq, "respawn pane failed: %s", cause);
free(cause);
environ_free(&env);
environ_free(env);
return (CMD_RETURN_ERROR);
}
wp->flags |= PANE_REDRAW;
server_status_window(w);
environ_free(&env);
environ_free(env);
return (CMD_RETURN_NORMAL);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@ -30,45 +30,45 @@
enum cmd_retval cmd_respawn_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_respawn_window_entry = {
"respawn-window", "respawnw",
"kt:", 0, 1,
"[-k] " CMD_TARGET_WINDOW_USAGE " [command]",
0,
NULL,
NULL,
cmd_respawn_window_exec
.name = "respawn-window",
.alias = "respawnw",
.args = { "kt:", 0, -1 },
.usage = "[-k] " CMD_TARGET_WINDOW_USAGE " [command]",
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_respawn_window_exec
};
enum cmd_retval
cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct winlink *wl;
struct window *w;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl;
struct window *w = wl->window;
struct window_pane *wp;
struct session *s;
struct environ env;
const char *cmd;
struct environ *env;
const char *path;
char *cause;
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), &s)) == NULL)
return (CMD_RETURN_ERROR);
w = wl->window;
struct environ_entry *envent;
if (!args_has(self->args, 'k')) {
TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->fd == -1)
continue;
cmdq_error(cmdq,
"window still active: %s:%d", s->name, wl->idx);
cmdq_error(cmdq, "window still active: %s:%d", s->name,
wl->idx);
return (CMD_RETURN_ERROR);
}
}
environ_init(&env);
environ_copy(&global_environ, &env);
environ_copy(&s->environ, &env);
server_fill_environ(s, &env);
env = environ_create();
environ_copy(global_environ, env);
environ_copy(s->environ, env);
server_fill_environ(s, env);
wp = TAILQ_FIRST(&w->panes);
TAILQ_REMOVE(&w->panes, wp, entry);
@ -76,15 +76,21 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
window_destroy_panes(w);
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
window_pane_resize(wp, w->sx, w->sy);
if (args->argc != 0)
cmd = args->argv[0];
path = NULL;
if (cmdq->client != NULL && cmdq->client->session == NULL)
envent = environ_find(cmdq->client->environ, "PATH");
else
cmd = NULL;
if (window_pane_spawn(wp, cmd, NULL, NULL, &env, s->tio, &cause) != 0) {
envent = environ_find(s->environ, "PATH");
if (envent != NULL)
path = envent->value;
if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, NULL, env,
s->tio, &cause) != 0) {
cmdq_error(cmdq, "respawn window failed: %s", cause);
free(cause);
environ_free(&env);
server_destroy_pane(wp);
environ_free(env);
server_destroy_pane(wp, 0);
return (CMD_RETURN_ERROR);
}
layout_init(w, wp);
@ -96,6 +102,6 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
recalculate_sizes();
server_redraw_window(w);
environ_free(&env);
environ_free(env);
return (CMD_RETURN_NORMAL);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@ -24,41 +24,30 @@
* Rotate the panes in a window.
*/
void cmd_rotate_window_key_binding(struct cmd *, int);
enum cmd_retval cmd_rotate_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_rotate_window_entry = {
"rotate-window", "rotatew",
"Dt:U", 0, 0,
"[-DU] " CMD_TARGET_WINDOW_USAGE,
0,
cmd_rotate_window_key_binding,
NULL,
cmd_rotate_window_exec
};
.name = "rotate-window",
.alias = "rotatew",
void
cmd_rotate_window_key_binding(struct cmd *self, int key)
{
self->args = args_create(0);
if (key == ('o' | KEYC_ESCAPE))
args_set(self->args, 'D', NULL);
}
.args = { "Dt:U", 0, 0 },
.usage = "[-DU] " CMD_TARGET_WINDOW_USAGE,
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_rotate_window_exec
};
enum cmd_retval
cmd_rotate_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct winlink *wl;
struct window *w;
struct winlink *wl = cmdq->state.tflag.wl;
struct window *w = wl->window;
struct window_pane *wp, *wp2;
struct layout_cell *lc;
u_int sx, sy, xoff, yoff;
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR);
w = wl->window;
if (args_has(self->args, 'D')) {
wp = TAILQ_LAST(&w->panes, window_panes);
TAILQ_REMOVE(&w->panes, wp, entry);

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@ -36,13 +36,16 @@ void cmd_run_shell_free(void *);
void cmd_run_shell_print(struct job *, const char *);
const struct cmd_entry cmd_run_shell_entry = {
"run-shell", "run",
"bt:", 1, 1,
"[-b] " CMD_TARGET_PANE_USAGE " shell-command",
0,
NULL,
NULL,
cmd_run_shell_exec
.name = "run-shell",
.alias = "run",
.args = { "bt:", 1, 1 },
.usage = "[-b] " CMD_TARGET_PANE_USAGE " shell-command",
.tflag = CMD_PANE_CANFAIL,
.flags = 0,
.exec = cmd_run_shell_exec
};
struct cmd_run_shell_data {
@ -77,30 +80,20 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_q *cmdq)
struct args *args = self->args;
struct cmd_run_shell_data *cdata;
char *shellcmd;
struct client *c;
struct session *s = NULL;
struct winlink *wl = NULL;
struct window_pane *wp = NULL;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl;
struct window_pane *wp = cmdq->state.tflag.wp;
struct format_tree *ft;
const char *cwd;
if (args_has(args, 't'))
wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp);
else {
c = cmd_find_client(cmdq, NULL, 1);
if (c != NULL && c->session != NULL) {
s = c->session;
wl = s->curw;
wp = wl->window->active;
}
}
ft = format_create();
if (s != NULL)
format_session(ft, s);
if (s != NULL && wl != NULL)
format_winlink(ft, s, wl);
if (wp != NULL)
format_window_pane(ft, wp);
if (cmdq->client != NULL && cmdq->client->session == NULL)
cwd = cmdq->client->cwd;
else if (s != NULL)
cwd = s->cwd;
else
cwd = NULL;
ft = format_create(cmdq, 0);
format_defaults(ft, NULL, s, wl, wp);
shellcmd = format_expand(ft, args->argv[0]);
format_free(ft);
@ -112,7 +105,8 @@ cmd_run_shell_exec(struct cmd *self, struct cmd_q *cmdq)
cdata->cmdq = cmdq;
cmdq->references++;
job_run(shellcmd, s, cmd_run_shell_callback, cmd_run_shell_free, cdata);
job_run(shellcmd, s, cwd, cmd_run_shell_callback, cmd_run_shell_free,
cdata);
if (cdata->bflag)
return (CMD_RETURN_NORMAL);
@ -129,7 +123,7 @@ cmd_run_shell_callback(struct job *job)
int retcode;
u_int lines;
if (cmdq->dead)
if (cmdq->flags & CMD_Q_DEAD)
return;
cmd = cdata->cmd;
@ -162,13 +156,9 @@ cmd_run_shell_callback(struct job *job)
retcode = WTERMSIG(job->status);
xasprintf(&msg, "'%s' terminated by signal %d", cmd, retcode);
}
if (msg != NULL) {
if (lines == 0)
cmdq_info(cmdq, "%s", msg);
else
cmd_run_shell_print(job, msg);
free(msg);
}
if (msg != NULL)
cmd_run_shell_print(job, msg);
free(msg);
}
void

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@ -20,8 +20,10 @@
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h"
@ -32,67 +34,60 @@
enum cmd_retval cmd_save_buffer_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_save_buffer_entry = {
"save-buffer", "saveb",
"ab:", 1, 1,
"[-a] " CMD_BUFFER_USAGE " path",
0,
NULL,
NULL,
cmd_save_buffer_exec
.name = "save-buffer",
.alias = "saveb",
.args = { "ab:", 1, 1 },
.usage = "[-a] " CMD_BUFFER_USAGE " path",
.flags = 0,
.exec = cmd_save_buffer_exec
};
const struct cmd_entry cmd_show_buffer_entry = {
"show-buffer", "showb",
"b:", 0, 0,
CMD_BUFFER_USAGE,
0,
NULL,
NULL,
cmd_save_buffer_exec
.name = "show-buffer",
.alias = "showb",
.args = { "b:", 0, 0 },
.usage = CMD_BUFFER_USAGE,
.flags = 0,
.exec = cmd_save_buffer_exec
};
enum cmd_retval
cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
struct client *c = cmdq->client;
struct session *s;
struct paste_buffer *pb;
const char *path, *newpath, *wd;
char *cause, *start, *end;
size_t size, used;
int buffer;
mode_t mask;
const char *path, *bufname, *bufdata, *start, *end, *cwd;
const char *flags;
char *msg, *file, resolved[PATH_MAX];
size_t size, used, msglen, bufsize;
FILE *f;
char *msg;
size_t msglen;
if (!args_has(args, 'b')) {
if ((pb = paste_get_top(&global_buffers)) == NULL) {
if ((pb = paste_get_top(NULL)) == NULL) {
cmdq_error(cmdq, "no buffers");
return (CMD_RETURN_ERROR);
}
} else {
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
if (cause != NULL) {
cmdq_error(cmdq, "buffer %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
pb = paste_get_index(&global_buffers, buffer);
bufname = args_get(args, 'b');
pb = paste_get_name(bufname);
if (pb == NULL) {
cmdq_error(cmdq, "no buffer %d", buffer);
cmdq_error(cmdq, "no buffer %s", bufname);
return (CMD_RETURN_ERROR);
}
}
bufdata = paste_buffer_data(pb, &bufsize);
if (self->entry == &cmd_show_buffer_entry)
path = "-";
else
path = args->argv[0];
if (strcmp(path, "-") == 0) {
c = cmdq->client;
if (c == NULL) {
cmdq_error(cmdq, "can't write to stdout");
return (CMD_RETURN_ERROR);
@ -102,33 +97,35 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
goto do_print;
}
c = cmdq->client;
if (c != NULL)
wd = c->cwd;
else if ((s = cmd_current_session(cmdq, 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;
}
mask = umask(S_IRWXG | S_IRWXO);
if (args_has(self->args, 'a'))
f = fopen(path, "ab");
if (c != NULL && c->session == NULL)
cwd = c->cwd;
else if ((s = c->session) != NULL)
cwd = s->cwd;
else
f = fopen(path, "wb");
umask(mask);
if (f == NULL) {
cmdq_error(cmdq, "%s: %s", path, strerror(errno));
cwd = ".";
flags = "wb";
if (args_has(self->args, 'a'))
flags = "ab";
if (*path == '/')
file = xstrdup(path);
else
xasprintf(&file, "%s/%s", cwd, path);
if (realpath(file, resolved) == NULL &&
strlcpy(resolved, file, sizeof resolved) >= sizeof resolved) {
cmdq_error(cmdq, "%s: %s", file, strerror(ENAMETOOLONG));
return (CMD_RETURN_ERROR);
}
if (fwrite(pb->data, 1, pb->size, f) != pb->size) {
cmdq_error(cmdq, "%s: fwrite error", path);
f = fopen(resolved, flags);
free(file);
if (f == NULL) {
cmdq_error(cmdq, "%s: %s", resolved, strerror(errno));
return (CMD_RETURN_ERROR);
}
if (fwrite(bufdata, 1, bufsize, f) != bufsize) {
cmdq_error(cmdq, "%s: write error", resolved);
fclose(f);
return (CMD_RETURN_ERROR);
}
@ -137,29 +134,28 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_NORMAL);
do_stdout:
evbuffer_add(c->stdout_data, pb->data, pb->size);
server_push_stdout(c);
evbuffer_add(c->stdout_data, bufdata, bufsize);
server_client_push_stdout(c);
return (CMD_RETURN_NORMAL);
do_print:
if (pb->size > (INT_MAX / 4) - 1) {
if (bufsize > (INT_MAX / 4) - 1) {
cmdq_error(cmdq, "buffer too big");
return (CMD_RETURN_ERROR);
}
msg = NULL;
msglen = 0;
used = 0;
while (used != pb->size) {
start = pb->data + used;
end = memchr(start, '\n', pb->size - used);
while (used != bufsize) {
start = bufdata + used;
end = memchr(start, '\n', bufsize - used);
if (end != NULL)
size = end - start;
else
size = pb->size - used;
size = bufsize - used;
msglen = size * 4 + 1;
msg = xrealloc(msg, 1, msglen);
msg = xrealloc(msg, msglen);
strvisx(msg, start, size, VIS_OCTAL|VIS_TAB);
cmdq_print(cmdq, "%s", msg);

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@ -18,118 +18,122 @@
#include <sys/types.h>
#include <stdlib.h>
#include "tmux.h"
/*
* Switch window to selected layout.
*/
void cmd_select_layout_key_binding(struct cmd *, int);
enum cmd_retval cmd_select_layout_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_select_layout_entry = {
"select-layout", "selectl",
"npt:", 0, 1,
"[-np] " CMD_TARGET_WINDOW_USAGE " [layout-name]",
0,
cmd_select_layout_key_binding,
NULL,
cmd_select_layout_exec
.name = "select-layout",
.alias = "selectl",
.args = { "nopt:", 0, 1 },
.usage = "[-nop] " CMD_TARGET_WINDOW_USAGE " [layout-name]",
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_select_layout_exec
};
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
.name = "next-layout",
.alias = "nextl",
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_WINDOW_USAGE,
.tflag = CMD_WINDOW,
.flags = 0,
.exec = 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
};
.name = "previous-layout",
.alias = "prevl",
void
cmd_select_layout_key_binding(struct cmd *self, int key)
{
switch (key) {
case '1' | KEYC_ESCAPE:
self->args = args_create(1, "even-horizontal");
break;
case '2' | KEYC_ESCAPE:
self->args = args_create(1, "even-vertical");
break;
case '3' | KEYC_ESCAPE:
self->args = args_create(1, "main-horizontal");
break;
case '4' | KEYC_ESCAPE:
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;
}
}
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_WINDOW_USAGE,
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_select_layout_exec
};
enum cmd_retval
cmd_select_layout_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct winlink *wl;
struct winlink *wl = cmdq->state.tflag.wl;
struct window *w;
const char *layoutname;
char *oldlayout;
int next, previous, layout;
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), NULL)) == NULL)
return (CMD_RETURN_ERROR);
server_unzoom_window(wl->window);
w = wl->window;
server_unzoom_window(w);
next = self->entry == &cmd_next_layout_entry;
if (args_has(self->args, 'n'))
if (args_has(args, 'n'))
next = 1;
previous = self->entry == &cmd_previous_layout_entry;
if (args_has(self->args, 'p'))
if (args_has(args, 'p'))
previous = 1;
oldlayout = w->old_layout;
w->old_layout = layout_dump(w->layout_root);
if (next || previous) {
if (next)
layout = layout_set_next(wl->window);
layout_set_next(w);
else
layout = layout_set_previous(wl->window);
server_redraw_window(wl->window);
cmdq_info(cmdq, "arranging in: %s", layout_set_name(layout));
return (CMD_RETURN_NORMAL);
layout_set_previous(w);
goto changed;
}
if (args->argc == 0)
layout = wl->window->lastlayout;
else
layout = layout_set_lookup(args->argv[0]);
if (layout != -1) {
layout = layout_set_select(wl->window, layout);
server_redraw_window(wl->window);
cmdq_info(cmdq, "arranging in: %s", layout_set_name(layout));
return (CMD_RETURN_NORMAL);
}
if (args->argc != 0) {
layoutname = args->argv[0];
if (layout_parse(wl->window, layoutname) == -1) {
cmdq_error(cmdq, "can't set layout: %s", layoutname);
return (CMD_RETURN_ERROR);
if (!args_has(args, 'o')) {
if (args->argc == 0)
layout = w->lastlayout;
else
layout = layout_set_lookup(args->argv[0]);
if (layout != -1) {
layout_set_select(w, layout);
goto changed;
}
server_redraw_window(wl->window);
cmdq_info(cmdq, "arranging in: %s", layoutname);
}
if (args->argc != 0)
layoutname = args->argv[0];
else if (args_has(args, 'o'))
layoutname = oldlayout;
else
layoutname = NULL;
if (layoutname != NULL) {
if (layout_parse(w, layoutname) == -1) {
cmdq_error(cmdq, "can't set layout: %s", layoutname);
goto error;
}
goto changed;
}
free(oldlayout);
return (CMD_RETURN_NORMAL);
changed:
free(oldlayout);
server_redraw_window(w);
return (CMD_RETURN_NORMAL);
error:
free(w->old_layout);
w->old_layout = oldlayout;
return (CMD_RETURN_ERROR);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@ -24,95 +24,147 @@
* Select pane.
*/
void cmd_select_pane_key_binding(struct cmd *, int);
enum cmd_retval cmd_select_pane_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_select_pane_entry = {
"select-pane", "selectp",
"lDLRt:U", 0, 0,
"[-lDLRU] " CMD_TARGET_PANE_USAGE,
0,
cmd_select_pane_key_binding,
NULL,
cmd_select_pane_exec
.name = "select-pane",
.alias = "selectp",
.args = { "DdegLlMmP:Rt:U", 0, 0 },
.usage = "[-DdegLlMmRU] [-P style] " CMD_TARGET_PANE_USAGE,
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_select_pane_exec
};
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
};
.name = "last-pane",
.alias = "lastp",
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', ":.+");
}
.args = { "det:", 0, 0 },
.usage = "[-de] " CMD_TARGET_WINDOW_USAGE,
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_select_pane_exec
};
enum cmd_retval
cmd_select_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct winlink *wl;
struct window_pane *wp;
struct winlink *wl = cmdq->state.tflag.wl;
struct window *w = wl->window;
struct session *s = cmdq->state.tflag.s;
struct window_pane *wp = cmdq->state.tflag.wp, *lastwp, *markedwp;
const char *style;
if (self->entry == &cmd_last_pane_entry || args_has(args, 'l')) {
wl = cmd_find_window(cmdq, args_get(args, 't'), NULL);
if (wl == NULL)
return (CMD_RETURN_ERROR);
if (wl->window->last == NULL) {
cmdq_error(cmdq, "no last pane");
return (CMD_RETURN_ERROR);
}
server_unzoom_window(wl->window);
window_set_active_pane(wl->window, wl->window->last);
server_status_window(wl->window);
server_redraw_window_borders(wl->window);
if (args_has(self->args, 'e'))
w->last->flags &= ~PANE_INPUTOFF;
else if (args_has(self->args, 'd'))
w->last->flags |= PANE_INPUTOFF;
else {
server_unzoom_window(w);
window_redraw_active_switch(w, w->last);
if (window_set_active_pane(w, w->last)) {
server_status_window(w);
server_redraw_window_borders(w);
}
}
return (CMD_RETURN_NORMAL);
}
if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp)) == NULL)
return (CMD_RETURN_ERROR);
server_unzoom_window(wp->window);
if (!window_pane_visible(wp)) {
cmdq_error(cmdq, "pane not visible");
return (CMD_RETURN_ERROR);
}
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) {
cmdq_error(cmdq, "pane not found");
return (CMD_RETURN_ERROR);
if (args_has(args, 'm') || args_has(args, 'M')) {
if (args_has(args, 'm') && !window_pane_visible(wp))
return (CMD_RETURN_NORMAL);
lastwp = marked_pane.wp;
if (args_has(args, 'M') || server_is_marked(s, wl, wp))
server_clear_marked();
else
server_set_marked(s, wl, wp);
markedwp = marked_pane.wp;
if (lastwp != NULL) {
server_redraw_window_borders(lastwp->window);
server_status_window(lastwp->window);
}
if (markedwp != NULL) {
server_redraw_window_borders(markedwp->window);
server_status_window(markedwp->window);
}
return (CMD_RETURN_NORMAL);
}
window_set_active_pane(wl->window, wp);
server_status_window(wl->window);
server_redraw_window_borders(wl->window);
if (args_has(self->args, 'P') || args_has(self->args, 'g')) {
if (args_has(args, 'P')) {
style = args_get(args, 'P');
if (style_parse(&grid_default_cell, &wp->colgc,
style) == -1) {
cmdq_error(cmdq, "bad style: %s", style);
return (CMD_RETURN_ERROR);
}
wp->flags |= PANE_REDRAW;
}
if (args_has(self->args, 'g'))
cmdq_print(cmdq, "%s", style_tostring(&wp->colgc));
return (CMD_RETURN_NORMAL);
}
if (args_has(self->args, 'L')) {
server_unzoom_window(wp->window);
wp = window_pane_find_left(wp);
} else if (args_has(self->args, 'R')) {
server_unzoom_window(wp->window);
wp = window_pane_find_right(wp);
} else if (args_has(self->args, 'U')) {
server_unzoom_window(wp->window);
wp = window_pane_find_up(wp);
} else if (args_has(self->args, 'D')) {
server_unzoom_window(wp->window);
wp = window_pane_find_down(wp);
}
if (wp == NULL)
return (CMD_RETURN_NORMAL);
if (args_has(self->args, 'e')) {
wp->flags &= ~PANE_INPUTOFF;
return (CMD_RETURN_NORMAL);
}
if (args_has(self->args, 'd')) {
wp->flags |= PANE_INPUTOFF;
return (CMD_RETURN_NORMAL);
}
if (wp == w->active)
return (CMD_RETURN_NORMAL);
server_unzoom_window(wp->window);
if (!window_pane_visible(wp)) {
cmdq_error(cmdq, "pane not visible");
return (CMD_RETURN_ERROR);
}
window_redraw_active_switch(w, wp);
if (window_set_active_pane(w, wp)) {
server_status_window(w);
server_redraw_window_borders(w);
}
return (CMD_RETURN_NORMAL);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -26,69 +26,65 @@
* Select window by index.
*/
void cmd_select_window_key_binding(struct cmd *, int);
enum cmd_retval cmd_select_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_select_window_entry = {
"select-window", "selectw",
"lnpTt:", 0, 0,
"[-lnpT] " CMD_TARGET_WINDOW_USAGE,
0,
cmd_select_window_key_binding,
NULL,
cmd_select_window_exec
.name = "select-window",
.alias = "selectw",
.args = { "lnpTt:", 0, 0 },
.usage = "[-lnpT] " CMD_TARGET_WINDOW_USAGE,
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_select_window_exec
};
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
.name = "next-window",
.alias = "next",
.args = { "at:", 0, 0 },
.usage = "[-a] " CMD_TARGET_SESSION_USAGE,
.tflag = CMD_SESSION,
.flags = 0,
.exec = 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
.name = "previous-window",
.alias = "prev",
.args = { "at:", 0, 0 },
.usage = "[-a] " CMD_TARGET_SESSION_USAGE,
.tflag = CMD_SESSION,
.flags = 0,
.exec = 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
.name = "last-window",
.alias = "last",
.args = { "t:", 0, 0 },
.usage = CMD_TARGET_SESSION_USAGE,
.tflag = CMD_SESSION,
.flags = 0,
.exec = cmd_select_window_exec
};
void
cmd_select_window_key_binding(struct cmd *self, int key)
{
char tmp[16];
self->args = args_create(0);
if (key >= '0' && key <= '9') {
xsnprintf(tmp, sizeof tmp, ":%d", key - '0');
args_set(self->args, 't', tmp);
}
if (key == ('n' | KEYC_ESCAPE) || key == ('p' | KEYC_ESCAPE))
args_set(self->args, 'a', NULL);
}
enum cmd_retval
cmd_select_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct winlink *wl;
struct session *s;
struct winlink *wl = cmdq->state.tflag.wl;
struct session *s = cmdq->state.tflag.s;
int next, previous, last, activity;
next = self->entry == &cmd_next_window_entry;
@ -102,10 +98,6 @@ cmd_select_window_exec(struct cmd *self, struct cmd_q *cmdq)
last = 1;
if (next || previous || last) {
s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
activity = args_has(self->args, 'a');
if (next) {
if (session_next(s, activity) != 0) {
@ -126,10 +118,6 @@ cmd_select_window_exec(struct cmd *self, struct cmd_q *cmdq)
server_redraw_session(s);
} else {
wl = cmd_find_window(cmdq, args_get(args, 't'), &s);
if (wl == NULL)
return (CMD_RETURN_ERROR);
/*
* If -T and select-window is invoked on same window as
* current, switch to previous window.

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@ -30,72 +30,76 @@
enum cmd_retval cmd_send_keys_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_send_keys_entry = {
"send-keys", "send",
"lRt:", 0, -1,
"[-lR] " CMD_TARGET_PANE_USAGE " key ...",
0,
NULL,
NULL,
cmd_send_keys_exec
.name = "send-keys",
.alias = "send",
.args = { "lRMt:", 0, -1 },
.usage = "[-lRM] " CMD_TARGET_PANE_USAGE " key ...",
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_send_keys_exec
};
const struct cmd_entry cmd_send_prefix_entry = {
"send-prefix", NULL,
"2t:", 0, 0,
"[-2] " CMD_TARGET_PANE_USAGE,
0,
NULL,
NULL,
cmd_send_keys_exec
.name = "send-prefix",
.alias = NULL,
.args = { "2t:", 0, 0 },
.usage = "[-2] " CMD_TARGET_PANE_USAGE,
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_send_keys_exec
};
enum cmd_retval
cmd_send_keys_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct window_pane *wp;
struct session *s;
struct input_ctx *ictx;
const char *str;
int i, key;
struct window_pane *wp = cmdq->state.tflag.wp;
struct session *s = cmdq->state.tflag.s;
struct mouse_event *m = &cmdq->item->mouse;
const u_char *keystr;
int i, literal;
key_code key;
if (cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp) == NULL)
return (CMD_RETURN_ERROR);
if (self->entry == &cmd_send_prefix_entry) {
if (args_has(args, '2'))
key = options_get_number(&s->options, "prefix2");
else
key = options_get_number(&s->options, "prefix");
window_pane_key(wp, s, key);
if (args_has(args, 'M')) {
wp = cmd_mouse_pane(m, &s, NULL);
if (wp == NULL) {
cmdq_error(cmdq, "no mouse target");
return (CMD_RETURN_ERROR);
}
window_pane_key(wp, NULL, s, m->key, m);
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'R')) {
ictx = &wp->ictx;
memcpy(&ictx->cell, &grid_default_cell, sizeof ictx->cell);
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);
if (self->entry == &cmd_send_prefix_entry) {
if (args_has(args, '2'))
key = options_get_number(s->options, "prefix2");
else
screen_write_start(&ictx->ctx, NULL, &wp->base);
screen_write_reset(&ictx->ctx);
screen_write_stop(&ictx->ctx);
key = options_get_number(s->options, "prefix");
window_pane_key(wp, NULL, s, key, NULL);
return (CMD_RETURN_NORMAL);
}
for (i = 0; i < args->argc; i++) {
str = args->argv[i];
if (args_has(args, 'R'))
input_reset(wp, 1);
if (!args_has(args, 'l') &&
(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);
for (i = 0; i < args->argc; i++) {
literal = args_has(args, 'l');
if (!literal) {
key = key_string_lookup_string(args->argv[i]);
if (key != KEYC_NONE && key != KEYC_UNKNOWN)
window_pane_key(wp, NULL, s, key, NULL);
else
literal = 1;
}
if (literal) {
for (keystr = args->argv[i]; *keystr != '\0'; keystr++)
window_pane_key(wp, NULL, s, *keystr, NULL);
}
}

View File

@ -1,174 +0,0 @@
/* $Id$ */
/*
* 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 <sys/utsname.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "tmux.h"
/*
* Show various information about server.
*/
enum cmd_retval cmd_server_info_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_server_info_entry = {
"server-info", "info",
"", 0, 0,
"",
0,
NULL,
NULL,
cmd_server_info_exec
};
enum cmd_retval
cmd_server_info_exec(unused struct cmd *self, struct cmd_q *cmdq)
{
struct tty_term *term;
struct client *c;
struct session *s;
struct winlink *wl;
struct window *w;
struct window_pane *wp;
struct tty_code *code;
const struct tty_term_code_entry *ent;
struct utsname un;
struct job *job;
struct grid *gd;
struct grid_line *gl;
u_int i, j, k, lines;
size_t size;
char out[80];
char *tim;
time_t t;
tim = ctime(&start_time);
*strchr(tim, '\n') = '\0';
cmdq_print(cmdq,
"tmux " VERSION ", pid %ld, started %s", (long) getpid(), tim);
cmdq_print(cmdq, "socket path %s, debug level %d", socket_path,
debug_level);
if (uname(&un) >= 0) {
cmdq_print(cmdq, "system is %s %s %s %s",
un.sysname, un.release, un.version, un.machine);
}
if (cfg_file != NULL)
cmdq_print(cmdq, "configuration file is %s", cfg_file);
else
cmdq_print(cmdq, "configuration file not specified");
cmdq_print(cmdq, "protocol version is %d", PROTOCOL_VERSION);
cmdq_print(cmdq, "%s", "");
cmdq_print(cmdq, "Clients:");
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c == NULL || c->session == NULL)
continue;
cmdq_print(cmdq,"%2d: %s (%d, %d): %s [%ux%u %s bs=%hho "
"class=%u] [flags=0x%x/0x%x, references=%u]", i,
c->tty.path, c->ibuf.fd, c->tty.fd, c->session->name,
c->tty.sx, c->tty.sy, c->tty.termname,
c->tty.tio.c_cc[VERASE], c->tty.class,
c->flags, c->tty.flags, c->references);
}
cmdq_print(cmdq, "%s", "");
cmdq_print(cmdq, "Sessions: [%zu]", sizeof (struct grid_cell));
RB_FOREACH(s, sessions, &sessions) {
t = s->creation_time.tv_sec;
tim = ctime(&t);
*strchr(tim, '\n') = '\0';
cmdq_print(cmdq, "%2u: %s: %u windows (created %s) [%ux%u] "
"[flags=0x%x]", s->id, s->name,
winlink_count(&s->windows), tim, s->sx, s->sy, s->flags);
RB_FOREACH(wl, winlinks, &s->windows) {
w = wl->window;
cmdq_print(cmdq, "%4u: %s [%ux%u] [flags=0x%x, "
"references=%u, last layout=%d]", wl->idx, w->name,
w->sx, w->sy, w->flags, w->references,
w->lastlayout);
j = 0;
TAILQ_FOREACH(wp, &w->panes, entry) {
lines = size = 0;
gd = wp->base.grid;
for (k = 0; k < gd->hsize + gd->sy; k++) {
gl = &gd->linedata[k];
if (gl->celldata == NULL)
continue;
lines++;
size += gl->cellsize *
sizeof *gl->celldata;
}
cmdq_print(cmdq,
"%6u: %s %lu %d %u/%u, %zu bytes", j,
wp->tty, (u_long) wp->pid, wp->fd, lines,
gd->hsize + gd->sy, size);
j++;
}
}
}
cmdq_print(cmdq, "%s", "");
cmdq_print(cmdq, "Terminals:");
LIST_FOREACH(term, &tty_terms, entry) {
cmdq_print(cmdq, "%s [references=%u, flags=0x%x]:",
term->name, term->references, term->flags);
for (i = 0; i < NTTYCODE; i++) {
ent = &tty_term_codes[i];
code = &term->codes[ent->code];
switch (code->type) {
case TTYCODE_NONE:
cmdq_print(cmdq, "%2u: %s: [missing]",
ent->code, ent->name);
break;
case TTYCODE_STRING:
strnvis(out, code->value.string, sizeof out,
VIS_OCTAL|VIS_TAB|VIS_NL);
cmdq_print(cmdq, "%2u: %s: (string) %s",
ent->code, ent->name, out);
break;
case TTYCODE_NUMBER:
cmdq_print(cmdq, "%2u: %s: (number) %d",
ent->code, ent->name, code->value.number);
break;
case TTYCODE_FLAG:
cmdq_print(cmdq, "%2u: %s: (flag) %s",
ent->code, ent->name,
code->value.flag ? "true" : "false");
break;
}
}
}
cmdq_print(cmdq, "%s", "");
cmdq_print(cmdq, "Jobs:");
LIST_FOREACH(job, &all_jobs, lentry) {
cmdq_print(cmdq, "%s [fd=%d, pid=%d, status=%d]",
job->cmd, job->fd, job->pid, job->status);
}
return (CMD_RETURN_NORMAL);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -24,51 +24,98 @@
#include "tmux.h"
/*
* Add or set a paste buffer.
* Add, set, append to or delete a paste buffer.
*/
enum cmd_retval cmd_set_buffer_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_set_buffer_entry = {
"set-buffer", "setb",
"b:", 1, 1,
CMD_BUFFER_USAGE " data",
0,
NULL,
NULL,
cmd_set_buffer_exec
.name = "set-buffer",
.alias = "setb",
.args = { "ab:n:", 0, 1 },
.usage = "[-a] " CMD_BUFFER_USAGE " [-n new-buffer-name] data",
.flags = 0,
.exec = cmd_set_buffer_exec
};
const struct cmd_entry cmd_delete_buffer_entry = {
.name = "delete-buffer",
.alias = "deleteb",
.args = { "b:", 0, 0 },
.usage = CMD_BUFFER_USAGE,
.flags = 0,
.exec = cmd_set_buffer_exec
};
enum cmd_retval
cmd_set_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
u_int limit;
char *pdata, *cause;
size_t psize;
int buffer;
struct args *args = self->args;
struct paste_buffer *pb;
char *bufdata, *cause;
const char *bufname, *olddata;
size_t bufsize, newsize;
limit = options_get_number(&global_options, "buffer-limit");
bufname = args_get(args, 'b');
if (bufname == NULL)
pb = NULL;
else
pb = paste_get_name(bufname);
pdata = xstrdup(args->argv[0]);
psize = strlen(pdata);
if (!args_has(args, 'b')) {
paste_add(&global_buffers, pdata, psize, limit);
if (self->entry == &cmd_delete_buffer_entry) {
if (pb == NULL)
pb = paste_get_top(&bufname);
if (pb == NULL) {
cmdq_error(cmdq, "no buffer");
return (CMD_RETURN_ERROR);
}
paste_free(pb);
return (CMD_RETURN_NORMAL);
}
buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
if (cause != NULL) {
cmdq_error(cmdq, "buffer %s", cause);
free(cause);
free(pdata);
return (CMD_RETURN_ERROR);
if (args_has(args, 'n')) {
if (pb == NULL)
pb = paste_get_top(&bufname);
if (pb == NULL) {
cmdq_error(cmdq, "no buffer");
return (CMD_RETURN_ERROR);
}
if (paste_rename(bufname, args_get(args, 'n'), &cause) != 0) {
cmdq_error(cmdq, "%s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
return (CMD_RETURN_NORMAL);
}
if (paste_replace(&global_buffers, buffer, pdata, psize) != 0) {
cmdq_error(cmdq, "no buffer %d", buffer);
free(pdata);
if (args->argc != 1) {
cmdq_error(cmdq, "no data specified");
return (CMD_RETURN_ERROR);
}
if ((newsize = strlen(args->argv[0])) == 0)
return (CMD_RETURN_NORMAL);
bufsize = 0;
bufdata = NULL;
if (args_has(args, 'a') && pb != NULL) {
olddata = paste_buffer_data(pb, &bufsize);
bufdata = xmalloc(bufsize);
memcpy(bufdata, olddata, bufsize);
}
bufdata = xrealloc(bufdata, bufsize + newsize);
memcpy(bufdata + bufsize, args->argv[0], newsize);
bufsize += newsize;
if (paste_set(bufdata, bufsize, bufname, &cause) != 0) {
cmdq_error(cmdq, "%s", cause);
free(bufdata);
free(cause);
return (CMD_RETURN_ERROR);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@ -30,20 +30,22 @@
enum cmd_retval cmd_set_environment_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_set_environment_entry = {
"set-environment", "setenv",
"grt:u", 1, 2,
"[-gru] " CMD_TARGET_SESSION_USAGE " name [value]",
0,
NULL,
NULL,
cmd_set_environment_exec
.name = "set-environment",
.alias = "setenv",
.args = { "grt:u", 1, 2 },
.usage = "[-gru] " CMD_TARGET_SESSION_USAGE " name [value]",
.tflag = CMD_SESSION_CANFAIL,
.flags = 0,
.exec = cmd_set_environment_exec
};
enum cmd_retval
cmd_set_environment_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct session *s;
struct environ *env;
const char *name, *value;
@ -62,13 +64,10 @@ cmd_set_environment_exec(struct cmd *self, struct cmd_q *cmdq)
else
value = args->argv[1];
if (args_has(self->args, 'g'))
env = &global_environ;
else {
if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
env = &s->environ;
}
if (args_has(self->args, 'g') || cmdq->state.tflag.s == NULL)
env = global_environ;
else
env = cmdq->state.tflag.s->environ;
if (args_has(self->args, 'u')) {
if (value != NULL) {
@ -81,13 +80,13 @@ cmd_set_environment_exec(struct cmd *self, struct cmd_q *cmdq)
cmdq_error(cmdq, "can't specify a value with -r");
return (CMD_RETURN_ERROR);
}
environ_set(env, name, NULL);
environ_clear(env, name);
} else {
if (value == NULL) {
cmdq_error(cmdq, "no value specified");
return (CMD_RETURN_ERROR);
}
environ_set(env, name, value);
environ_set(env, name, "%s", value);
}
return (CMD_RETURN_NORMAL);

120
cmd-set-hook.c Normal file
View File

@ -0,0 +1,120 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2012 Thomas Adam <thomas@xteddy.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"
/*
* Set or show global or session hooks.
*/
enum cmd_retval cmd_set_hook_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_set_hook_entry = {
.name = "set-hook",
.alias = NULL,
.args = { "gt:u", 1, 2 },
.usage = "[-gu] " CMD_TARGET_SESSION_USAGE " hook-name [command]",
.tflag = CMD_SESSION,
.flags = 0,
.exec = cmd_set_hook_exec
};
const struct cmd_entry cmd_show_hooks_entry = {
.name = "show-hooks",
.alias = NULL,
.args = { "gt:", 0, 1 },
.usage = "[-g] " CMD_TARGET_SESSION_USAGE,
.tflag = CMD_SESSION,
.flags = 0,
.exec = cmd_set_hook_exec
};
enum cmd_retval
cmd_set_hook_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct cmd_list *cmdlist;
struct hooks *hooks;
struct hook *hook;
char *cause, *tmp;
const char *name, *cmd;
if (args_has(args, 'g'))
hooks = global_hooks;
else
hooks = cmdq->state.tflag.s->hooks;
if (self->entry == &cmd_show_hooks_entry) {
hook = hooks_first(hooks);
while (hook != NULL) {
tmp = cmd_list_print(hook->cmdlist);
cmdq_print(cmdq, "%s -> %s", hook->name, tmp);
free(tmp);
hook = hooks_next(hook);
}
return (CMD_RETURN_NORMAL);
}
name = args->argv[0];
if (*name == '\0') {
cmdq_error(cmdq, "invalid hook name");
return (CMD_RETURN_ERROR);
}
if (args->argc < 2)
cmd = NULL;
else
cmd = args->argv[1];
if (args_has(args, 'u')) {
if (cmd != NULL) {
cmdq_error(cmdq, "command passed to unset hook: %s",
name);
return (CMD_RETURN_ERROR);
}
hooks_remove(hooks, name);
return (CMD_RETURN_NORMAL);
}
if (cmd == NULL) {
cmdq_error(cmdq, "no command to set hook: %s", name);
return (CMD_RETURN_ERROR);
}
if (cmd_string_parse(cmd, &cmdlist, NULL, 0, &cause) != 0) {
if (cause != NULL) {
cmdq_error(cmdq, "%s", cause);
free(cause);
}
return (CMD_RETURN_ERROR);
}
hooks_add(hooks, name, cmdlist);
cmd_list_free(cmdlist);
return (CMD_RETURN_NORMAL);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -60,39 +60,47 @@ struct options_entry *cmd_set_option_flag(struct cmd *, struct cmd_q *,
struct options_entry *cmd_set_option_choice(struct cmd *, struct cmd_q *,
const struct options_table_entry *, struct options *,
const char *);
struct options_entry *cmd_set_option_style(struct cmd *, struct cmd_q *,
const struct options_table_entry *, struct options *,
const char *);
const struct cmd_entry cmd_set_option_entry = {
"set-option", "set",
"agoqst:uw", 1, 2,
"[-agosquw] [-t target-session|target-window] option [value]",
0,
NULL,
NULL,
cmd_set_option_exec
.name = "set-option",
.alias = "set",
.args = { "agoqst:uw", 1, 2 },
.usage = "[-agosquw] [-t target-window] option [value]",
.tflag = CMD_WINDOW_CANFAIL,
.flags = 0,
.exec = cmd_set_option_exec
};
const struct cmd_entry cmd_set_window_option_entry = {
"set-window-option", "setw",
"agoqt:u", 1, 2,
"[-agoqu] " CMD_TARGET_WINDOW_USAGE " option [value]",
0,
NULL,
NULL,
cmd_set_option_exec
.name = "set-window-option",
.alias = "setw",
.args = { "agoqt:u", 1, 2 },
.usage = "[-agoqu] " CMD_TARGET_WINDOW_USAGE " option [value]",
.tflag = CMD_WINDOW_CANFAIL,
.flags = 0,
.exec = cmd_set_option_exec
};
enum cmd_retval
cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
const struct options_table_entry *table, *oe;
struct session *s;
struct winlink *wl;
struct client *c;
struct options *oo;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl;
struct window *w;
struct client *c;
const struct options_table_entry *oe;
struct options *oo;
const char *optstr, *valstr;
u_int i;
/* Get the option name and value. */
optstr = args->argv[0];
@ -110,36 +118,50 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
return (cmd_set_option_user(self, cmdq, optstr, valstr));
/* Find the option entry, try each table. */
table = oe = NULL;
if (options_table_find(optstr, &table, &oe) != 0) {
cmdq_error(cmdq, "ambiguous option: %s", optstr);
return (CMD_RETURN_ERROR);
oe = NULL;
if (options_table_find(optstr, &oe) != 0) {
if (!args_has(args, 'q')) {
cmdq_error(cmdq, "ambiguous option: %s", optstr);
return (CMD_RETURN_ERROR);
}
return (CMD_RETURN_NORMAL);
}
if (oe == NULL) {
cmdq_error(cmdq, "unknown option: %s", optstr);
return (CMD_RETURN_ERROR);
if (!args_has(args, 'q')) {
cmdq_error(cmdq, "unknown option: %s", optstr);
return (CMD_RETURN_ERROR);
}
return (CMD_RETURN_NORMAL);
}
/* Work out the tree from the table. */
if (table == server_options_table)
oo = &global_options;
else if (table == window_options_table) {
/* Work out the tree from the scope of the option. */
if (oe->scope == OPTIONS_TABLE_SERVER)
oo = global_options;
else if (oe->scope == OPTIONS_TABLE_WINDOW) {
if (args_has(self->args, 'g'))
oo = &global_w_options;
oo = global_w_options;
else {
wl = cmd_find_window(cmdq, args_get(args, 't'), NULL);
if (wl == NULL)
if (wl == NULL) {
cmdq_error(cmdq,
"couldn't set '%s'%s", optstr,
(!args_has(args, 't') && !args_has(args,
'g')) ? " need target window or -g" : "");
return (CMD_RETURN_ERROR);
oo = &wl->window->options;
}
oo = wl->window->options;
}
} else if (table == session_options_table) {
} else if (oe->scope == OPTIONS_TABLE_SESSION) {
if (args_has(self->args, 'g'))
oo = &global_s_options;
oo = global_s_options;
else {
s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL)
if (s == NULL) {
cmdq_error(cmdq,
"couldn't set '%s'%s", optstr,
(!args_has(args, 't') && !args_has(args,
'g')) ? " need target session or -g" : "");
return (CMD_RETURN_ERROR);
oo = &s->options;
}
oo = s->options;
}
} else {
cmdq_error(cmdq, "unknown table");
@ -152,31 +174,37 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_ERROR);
} else {
if (args_has(args, 'o') && options_find1(oo, optstr) != NULL) {
if (!args_has(args, 'q'))
cmdq_print(cmdq, "already set: %s", optstr);
if (!args_has(args, 'q')) {
cmdq_error(cmdq, "already set: %s", optstr);
return (CMD_RETURN_ERROR);
}
return (CMD_RETURN_NORMAL);
}
if (cmd_set_option_set(self, cmdq, oe, oo, valstr) != 0)
return (CMD_RETURN_ERROR);
}
/* Start or stop timers when automatic-rename changed. */
if (strcmp (oe->name, "automatic-rename") == 0) {
for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
if ((w = ARRAY_ITEM(&windows, i)) == NULL)
continue;
if (options_get_number(&w->options, "automatic-rename"))
queue_window_name(w);
else if (event_initialized(&w->name_timer))
evtimer_del(&w->name_timer);
/* Start or stop timers if necessary. */
if (strcmp(oe->name, "automatic-rename") == 0) {
RB_FOREACH(w, windows, &windows) {
if (options_get_number(w->options, "automatic-rename"))
w->active->flags |= PANE_CHANGED;
}
}
if (strcmp(oe->name, "key-table") == 0) {
TAILQ_FOREACH(c, &clients, entry)
server_client_set_key_table(c, NULL);
}
if (strcmp(oe->name, "status") == 0 ||
strcmp(oe->name, "status-interval") == 0)
status_timer_start_all();
if (strcmp(oe->name, "monitor-silence") == 0)
alerts_reset_all();
/* Update sizes and redraw. May not need it but meh. */
recalculate_sizes();
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
c = ARRAY_ITEM(&clients, i);
if (c != NULL && c->session != NULL)
TAILQ_FOREACH(c, &clients, entry) {
if (c->session != NULL)
server_redraw_client(c);
}
@ -185,41 +213,36 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
/* Set user option. */
enum cmd_retval
cmd_set_option_user(struct cmd *self, struct cmd_q *cmdq, const char* optstr,
cmd_set_option_user(struct cmd *self, struct cmd_q *cmdq, const char *optstr,
const char *valstr)
{
struct args *args = self->args;
struct session *s;
struct winlink *wl;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl;
struct options *oo;
if (args_has(args, 's'))
oo = &global_options;
oo = global_options;
else if (args_has(self->args, 'w') ||
self->entry == &cmd_set_window_option_entry) {
if (args_has(self->args, 'g'))
oo = &global_w_options;
else {
wl = cmd_find_window(cmdq, args_get(args, 't'), NULL);
if (wl == NULL)
return (CMD_RETURN_ERROR);
oo = &wl->window->options;
}
oo = global_w_options;
else
oo = wl->window->options;
} else {
if (args_has(self->args, 'g'))
oo = &global_s_options;
else {
s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
oo = &s->options;
}
oo = global_s_options;
else
oo = s->options;
}
if (args_has(args, 'u')) {
if (options_find1(oo, optstr) == NULL) {
cmdq_error(cmdq, "unknown option: %s", optstr);
return (CMD_RETURN_ERROR);
if (!args_has(args, 'q')) {
cmdq_error(cmdq, "unknown option: %s", optstr);
return (CMD_RETURN_ERROR);
}
return (CMD_RETURN_NORMAL);
}
if (valstr != NULL) {
cmdq_error(cmdq, "value passed to unset option: %s",
@ -233,54 +256,64 @@ cmd_set_option_user(struct cmd *self, struct cmd_q *cmdq, const char* optstr,
return (CMD_RETURN_ERROR);
}
if (args_has(args, 'o') && options_find1(oo, optstr) != NULL) {
if (!args_has(args, 'q'))
cmdq_print(cmdq, "already set: %s", optstr);
if (!args_has(args, 'q')) {
cmdq_error(cmdq, "already set: %s", optstr);
return (CMD_RETURN_ERROR);
}
return (CMD_RETURN_NORMAL);
}
options_set_string(oo, optstr, "%s", valstr);
if (!args_has(args, 'q')) {
cmdq_info(cmdq, "set option: %s -> %s", optstr,
valstr);
}
}
return (CMD_RETURN_NORMAL);
}
/* Unset an option. */
int
cmd_set_option_unset(struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo, const char *value)
const struct options_table_entry *oe, struct options *oo,
const char *value)
{
struct args *args = self->args;
if (args_has(args, 'g')) {
cmdq_error(cmdq, "can't unset global option: %s", oe->name);
return (-1);
}
if (value != NULL) {
cmdq_error(cmdq, "value passed to unset option: %s", oe->name);
return (-1);
}
options_remove(oo, oe->name);
if (!args_has(args, 'q'))
cmdq_info(cmdq, "unset option: %s", oe->name);
if (args_has(args, 'g') || oo == global_options) {
switch (oe->type) {
case OPTIONS_TABLE_STRING:
options_set_string(oo, oe->name, "%s", oe->default_str);
break;
case OPTIONS_TABLE_STYLE:
options_set_style(oo, oe->name, oe->default_str, 0);
break;
default:
options_set_number(oo, oe->name, oe->default_num);
break;
}
} else
options_remove(oo, oe->name);
return (0);
}
/* Set an option. */
int
cmd_set_option_set(struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo, const char *value)
const struct options_table_entry *oe, struct options *oo,
const char *value)
{
struct args *args = self->args;
struct options_entry *o;
const char *s;
if (oe->type != OPTIONS_TABLE_FLAG && value == NULL) {
cmdq_error(cmdq, "empty value");
return (-1);
switch (oe->type) {
case OPTIONS_TABLE_FLAG:
case OPTIONS_TABLE_CHOICE:
break;
default:
if (value == NULL) {
cmdq_error(cmdq, "empty value");
return (-1);
}
}
o = NULL;
@ -296,9 +329,13 @@ cmd_set_option_set(struct cmd *self, struct cmd_q *cmdq,
break;
case OPTIONS_TABLE_COLOUR:
o = cmd_set_option_colour(self, cmdq, oe, oo, value);
if (o != NULL)
style_update_new(oo, o->name, oe->style);
break;
case OPTIONS_TABLE_ATTRIBUTES:
o = cmd_set_option_attributes(self, cmdq, oe, oo, value);
if (o != NULL)
style_update_new(oo, o->name, oe->style);
break;
case OPTIONS_TABLE_FLAG:
o = cmd_set_option_flag(self, cmdq, oe, oo, value);
@ -306,20 +343,20 @@ cmd_set_option_set(struct cmd *self, struct cmd_q *cmdq,
case OPTIONS_TABLE_CHOICE:
o = cmd_set_option_choice(self, cmdq, oe, oo, value);
break;
case OPTIONS_TABLE_STYLE:
o = cmd_set_option_style(self, cmdq, oe, oo, value);
break;
}
if (o == NULL)
return (-1);
s = options_table_print_entry(oe, o, 0);
if (!args_has(args, 'q'))
cmdq_info(cmdq, "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_q *cmdq,
const struct options_table_entry *oe, struct options *oo, const char *value)
cmd_set_option_string(struct cmd *self, __unused struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo,
const char *value)
{
struct args *args = self->args;
struct options_entry *o;
@ -339,8 +376,9 @@ cmd_set_option_string(struct cmd *self, unused struct cmd_q *cmdq,
/* Set a number option. */
struct options_entry *
cmd_set_option_number(unused struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo, const char *value)
cmd_set_option_number(__unused struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo,
const char *value)
{
long long ll;
const char *errstr;
@ -356,12 +394,14 @@ cmd_set_option_number(unused struct cmd *self, struct cmd_q *cmdq,
/* Set a key option. */
struct options_entry *
cmd_set_option_key(unused struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo, const char *value)
cmd_set_option_key(__unused struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo,
const char *value)
{
int key;
key_code key;
if ((key = key_string_lookup_string(value)) == KEYC_NONE) {
key = key_string_lookup_string(value);
if (key == KEYC_UNKNOWN) {
cmdq_error(cmdq, "bad key: %s", value);
return (NULL);
}
@ -371,8 +411,9 @@ cmd_set_option_key(unused struct cmd *self, struct cmd_q *cmdq,
/* Set a colour option. */
struct options_entry *
cmd_set_option_colour(unused struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo, const char *value)
cmd_set_option_colour(__unused struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo,
const char *value)
{
int colour;
@ -386,8 +427,9 @@ cmd_set_option_colour(unused struct cmd *self, struct cmd_q *cmdq,
/* Set an attributes option. */
struct options_entry *
cmd_set_option_attributes(unused struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo, const char *value)
cmd_set_option_attributes(__unused struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo,
const char *value)
{
int attr;
@ -401,8 +443,9 @@ cmd_set_option_attributes(unused struct cmd *self, struct cmd_q *cmdq,
/* Set a flag option. */
struct options_entry *
cmd_set_option_flag(unused struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo, const char *value)
cmd_set_option_flag(__unused struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo,
const char *value)
{
int flag;
@ -428,29 +471,55 @@ cmd_set_option_flag(unused struct cmd *self, struct cmd_q *cmdq,
/* Set a choice option. */
struct options_entry *
cmd_set_option_choice(unused struct cmd *self, struct cmd_q *cmdq,
cmd_set_option_choice(__unused struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo,
const char *value)
{
const char **choicep;
int n, choice = -1;
n = 0;
for (choicep = oe->choices; *choicep != NULL; choicep++) {
n++;
if (strncmp(*choicep, value, strlen(value)) != 0)
continue;
if (value == NULL) {
choice = options_get_number(oo, oe->name);
if (choice < 2)
choice = !choice;
} else {
n = 0;
for (choicep = oe->choices; *choicep != NULL; choicep++) {
n++;
if (strncmp(*choicep, value, strlen(value)) != 0)
continue;
if (choice != -1) {
cmdq_error(cmdq, "ambiguous value: %s", value);
if (choice != -1) {
cmdq_error(cmdq, "ambiguous value: %s", value);
return (NULL);
}
choice = n - 1;
}
if (choice == -1) {
cmdq_error(cmdq, "unknown value: %s", value);
return (NULL);
}
choice = n - 1;
}
if (choice == -1) {
cmdq_error(cmdq, "unknown value: %s", value);
return (NULL);
}
return (options_set_number(oo, oe->name, choice));
}
/* Set a style option. */
struct options_entry *
cmd_set_option_style(struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *oe, struct options *oo,
const char *value)
{
struct args *args = self->args;
struct options_entry *o;
int append;
append = args_has(args, 'a');
if ((o = options_set_style(oo, oe->name, value, append)) == NULL) {
cmdq_error(cmdq, "bad style: %s", value);
return (NULL);
}
style_update_old(oo, oe->name, &o->style);
return (o);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@ -27,33 +27,77 @@
* Show environment.
*/
enum cmd_retval cmd_show_environment_exec(struct cmd *, struct cmd_q *);
enum cmd_retval cmd_show_environment_exec(struct cmd *, struct cmd_q *);
char *cmd_show_environment_escape(struct environ_entry *);
void cmd_show_environment_print(struct cmd *, struct cmd_q *,
struct environ_entry *);
const struct cmd_entry cmd_show_environment_entry = {
"show-environment", "showenv",
"gt:", 0, 1,
"[-g] " CMD_TARGET_SESSION_USAGE " [name]",
0,
NULL,
NULL,
cmd_show_environment_exec
.name = "show-environment",
.alias = "showenv",
.args = { "gst:", 0, 1 },
.usage = "[-gs] " CMD_TARGET_SESSION_USAGE " [name]",
.tflag = CMD_SESSION_CANFAIL,
.flags = 0,
.exec = cmd_show_environment_exec
};
char *
cmd_show_environment_escape(struct environ_entry *envent)
{
const char *value = envent->value;
char c, *out, *ret;
out = ret = xmalloc(strlen(value) * 2 + 1); /* at most twice the size */
while ((c = *value++) != '\0') {
/* POSIX interprets $ ` " and \ in double quotes. */
if (c == '$' || c == '`' || c == '"' || c == '\\')
*out++ = '\\';
*out++ = c;
}
*out = '\0';
return (ret);
}
void
cmd_show_environment_print(struct cmd *self, struct cmd_q *cmdq,
struct environ_entry *envent)
{
char *escaped;
if (!args_has(self->args, 's')) {
if (envent->value != NULL)
cmdq_print(cmdq, "%s=%s", envent->name, envent->value);
else
cmdq_print(cmdq, "-%s", envent->name);
return;
}
if (envent->value != NULL) {
escaped = cmd_show_environment_escape(envent);
cmdq_print(cmdq, "%s=\"%s\"; export %s;", envent->name, escaped,
envent->name);
free(escaped);
} else
cmdq_print(cmdq, "unset %s;", envent->name);
}
enum cmd_retval
cmd_show_environment_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct session *s;
struct environ *env;
struct environ_entry *envent;
if (args_has(self->args, 'g'))
env = &global_environ;
else {
if ((s = cmd_find_session(cmdq, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
env = &s->environ;
}
if (args_has(self->args, 'g') || cmdq->state.tflag.s == NULL)
env = global_environ;
else
env = cmdq->state.tflag.s->environ;
if (args->argc != 0) {
envent = environ_find(env, args->argv[0]);
@ -61,19 +105,14 @@ cmd_show_environment_exec(struct cmd *self, struct cmd_q *cmdq)
cmdq_error(cmdq, "unknown variable: %s", args->argv[0]);
return (CMD_RETURN_ERROR);
}
if (envent->value != NULL)
cmdq_print(cmdq, "%s=%s", envent->name, envent->value);
else
cmdq_print(cmdq, "-%s", envent->name);
cmd_show_environment_print(self, cmdq, envent);
return (CMD_RETURN_NORMAL);
}
RB_FOREACH(envent, environ, env) {
if (envent->value != NULL)
cmdq_print(cmdq, "%s=%s", envent->name, envent->value);
else
cmdq_print(cmdq, "-%s", envent->name);
envent = environ_first(env);
while (envent != NULL) {
cmd_show_environment_print(self, cmdq, envent);
envent = environ_next(envent);
}
return (CMD_RETURN_NORMAL);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@ -20,6 +20,7 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "tmux.h"
@ -30,30 +31,94 @@
enum cmd_retval cmd_show_messages_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_show_messages_entry = {
"show-messages", "showmsgs",
"t:", 0, 0,
CMD_TARGET_CLIENT_USAGE,
0,
NULL,
NULL,
cmd_show_messages_exec
.name = "show-messages",
.alias = "showmsgs",
.args = { "JTt:", 0, 0 },
.usage = "[-JT] " CMD_TARGET_CLIENT_USAGE,
.tflag = CMD_CLIENT,
.flags = 0,
.exec = cmd_show_messages_exec
};
const struct cmd_entry cmd_server_info_entry = {
.name = "server-info",
.alias = "info",
.args = { "", 0, 0 },
.usage = "",
.flags = 0,
.exec = cmd_show_messages_exec
};
int cmd_show_messages_terminals(struct cmd_q *, int);
int cmd_show_messages_jobs(struct cmd_q *, int);
int
cmd_show_messages_terminals(struct cmd_q *cmdq, int blank)
{
struct tty_term *term;
u_int i, n;
n = 0;
LIST_FOREACH(term, &tty_terms, entry) {
if (blank) {
cmdq_print(cmdq, "%s", "");
blank = 0;
}
cmdq_print(cmdq, "Terminal %u: %s [references=%u, flags=0x%x]:",
n, term->name, term->references, term->flags);
n++;
for (i = 0; i < tty_term_ncodes(); i++)
cmdq_print(cmdq, "%s", tty_term_describe(term, i));
}
return (n != 0);
}
int
cmd_show_messages_jobs(struct cmd_q *cmdq, int blank)
{
struct job *job;
u_int n;
n = 0;
LIST_FOREACH(job, &all_jobs, lentry) {
if (blank) {
cmdq_print(cmdq, "%s", "");
blank = 0;
}
cmdq_print(cmdq, "Job %u: %s [fd=%d, pid=%d, status=%d]",
n, job->cmd, job->fd, job->pid, job->status);
n++;
}
return (n != 0);
}
enum cmd_retval
cmd_show_messages_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
struct client *c = cmdq->state.c;
struct message_entry *msg;
char *tim;
u_int i;
int done, blank;
if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
for (i = 0; i < ARRAY_LENGTH(&c->message_log); i++) {
msg = &ARRAY_ITEM(&c->message_log, i);
done = blank = 0;
if (args_has(args, 'T') || self->entry == &cmd_server_info_entry) {
blank = cmd_show_messages_terminals(cmdq, blank);
done = 1;
}
if (args_has(args, 'J') || self->entry == &cmd_server_info_entry) {
cmd_show_messages_jobs(cmdq, blank);
done = 1;
}
if (done)
return (CMD_RETURN_NORMAL);
TAILQ_FOREACH(msg, &c->message_log, entry) {
tim = ctime(&msg->msg_time);
*strchr(tim, '\n') = '\0';

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -32,67 +32,65 @@ enum cmd_retval cmd_show_options_exec(struct cmd *, struct cmd_q *);
enum cmd_retval cmd_show_options_one(struct cmd *, struct cmd_q *,
struct options *, int);
enum cmd_retval cmd_show_options_all(struct cmd *, struct cmd_q *,
const struct options_table_entry *, struct options *);
struct options *, enum options_table_scope);
const struct cmd_entry cmd_show_options_entry = {
"show-options", "show",
"gqst:vw", 0, 1,
"[-gqsvw] [-t target-session|target-window] [option]",
0,
NULL,
NULL,
cmd_show_options_exec
.name = "show-options",
.alias = "show",
.args = { "gqst:vw", 0, 1 },
.usage = "[-gqsvw] [-t target-session|target-window] [option]",
.tflag = CMD_WINDOW_CANFAIL,
.flags = 0,
.exec = cmd_show_options_exec
};
const struct cmd_entry cmd_show_window_options_entry = {
"show-window-options", "showw",
"gvt:", 0, 1,
"[-gv] " CMD_TARGET_WINDOW_USAGE " [option]",
0,
NULL,
NULL,
cmd_show_options_exec
.name = "show-window-options",
.alias = "showw",
.args = { "gvt:", 0, 1 },
.usage = "[-gv] " CMD_TARGET_WINDOW_USAGE " [option]",
.tflag = CMD_WINDOW_CANFAIL,
.flags = 0,
.exec = cmd_show_options_exec
};
enum cmd_retval
cmd_show_options_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct session *s;
struct winlink *wl;
const struct options_table_entry *table;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl;
struct options *oo;
enum options_table_scope scope;
int quiet;
if (args_has(self->args, 's')) {
oo = &global_options;
table = server_options_table;
oo = global_options;
scope = OPTIONS_TABLE_SERVER;
} else if (args_has(self->args, 'w') ||
self->entry == &cmd_show_window_options_entry) {
table = window_options_table;
scope = OPTIONS_TABLE_WINDOW;
if (args_has(self->args, 'g'))
oo = &global_w_options;
else {
wl = cmd_find_window(cmdq, args_get(args, 't'), NULL);
if (wl == NULL)
return (CMD_RETURN_ERROR);
oo = &wl->window->options;
}
oo = global_w_options;
else
oo = wl->window->options;
} else {
table = session_options_table;
scope = OPTIONS_TABLE_SESSION;
if (args_has(self->args, 'g'))
oo = &global_s_options;
else {
s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
oo = &s->options;
}
oo = global_s_options;
else
oo = s->options;
}
quiet = args_has(self->args, 'q');
if (args->argc == 0)
return (cmd_show_options_all(self, cmdq, table, oo));
return (cmd_show_options_all(self, cmdq, oo, scope));
else
return (cmd_show_options_one(self, cmdq, oo, quiet));
}
@ -102,15 +100,17 @@ cmd_show_options_one(struct cmd *self, struct cmd_q *cmdq,
struct options *oo, int quiet)
{
struct args *args = self->args;
const struct options_table_entry *table, *oe;
const char *name = args->argv[0];
const struct options_table_entry *oe;
struct options_entry *o;
const char *optval;
if (*args->argv[0] == '@') {
if ((o = options_find1(oo, args->argv[0])) == NULL) {
retry:
if (*name == '@') {
if ((o = options_find1(oo, name)) == NULL) {
if (quiet)
return (CMD_RETURN_NORMAL);
cmdq_error(cmdq, "unknown option: %s", args->argv[0]);
cmdq_error(cmdq, "unknown option: %s", name);
return (CMD_RETURN_ERROR);
}
if (args_has(self->args, 'v'))
@ -120,17 +120,21 @@ cmd_show_options_one(struct cmd *self, struct cmd_q *cmdq,
return (CMD_RETURN_NORMAL);
}
table = oe = NULL;
if (options_table_find(args->argv[0], &table, &oe) != 0) {
cmdq_error(cmdq, "ambiguous option: %s", args->argv[0]);
oe = NULL;
if (options_table_find(name, &oe) != 0) {
cmdq_error(cmdq, "ambiguous option: %s", name);
return (CMD_RETURN_ERROR);
}
if (oe == NULL) {
if (quiet)
return (CMD_RETURN_NORMAL);
cmdq_error(cmdq, "unknown option: %s", args->argv[0]);
return (CMD_RETURN_NORMAL);
cmdq_error(cmdq, "unknown option: %s", name);
return (CMD_RETURN_ERROR);
}
if (oe->style != NULL) {
name = oe->style;
goto retry;
}
if ((o = options_find1(oo, oe->name)) == NULL)
return (CMD_RETURN_NORMAL);
optval = options_table_print_entry(oe, o, args_has(self->args, 'v'));
@ -142,28 +146,33 @@ cmd_show_options_one(struct cmd *self, struct cmd_q *cmdq,
}
enum cmd_retval
cmd_show_options_all(struct cmd *self, struct cmd_q *cmdq,
const struct options_table_entry *table, struct options *oo)
cmd_show_options_all(struct cmd *self, struct cmd_q *cmdq, struct options *oo,
enum options_table_scope scope)
{
const struct options_table_entry *oe;
struct options_entry *o;
const char *optval;
int vflag;
RB_FOREACH(o, options_tree, &oo->tree) {
o = options_first(oo);
while (o != NULL) {
if (*o->name == '@') {
if (args_has(self->args, 'v'))
cmdq_print(cmdq, "%s", o->str);
else
cmdq_print(cmdq, "%s \"%s\"", o->name, o->str);
}
o = options_next(o);
}
for (oe = table; oe->name != NULL; oe++) {
vflag = args_has(self->args, 'v');
for (oe = options_table; oe->name != NULL; oe++) {
if (oe->style != NULL || oe->scope != scope)
continue;
if ((o = options_find1(oo, oe->name)) == NULL)
continue;
optval = options_table_print_entry(oe, o,
args_has(self->args, 'v'));
if (args_has(self->args, 'v'))
optval = options_table_print_entry(oe, o, vflag);
if (vflag)
cmdq_print(cmdq, "%s", optval);
else
cmdq_print(cmdq, "%s %s", oe->name, optval);

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Tiago Cunha <me@tiagocunha.org>
@ -28,17 +28,17 @@
enum cmd_retval cmd_source_file_exec(struct cmd *, struct cmd_q *);
void cmd_source_file_show(struct cmd_q *);
void cmd_source_file_done(struct cmd_q *);
const struct cmd_entry cmd_source_file_entry = {
"source-file", "source",
"", 1, 1,
"path",
0,
NULL,
NULL,
cmd_source_file_exec
.name = "source-file",
.alias = "source",
.args = { "", 1, 1 },
.usage = "path",
.flags = 0,
.exec = cmd_source_file_exec
};
enum cmd_retval
@ -48,7 +48,7 @@ cmd_source_file_exec(struct cmd *self, struct cmd_q *cmdq)
struct cmd_q *cmdq1;
char *cause;
cmdq1 = cmdq_new(NULL);
cmdq1 = cmdq_new(cmdq->client);
cmdq1->emptyfn = cmd_source_file_done;
cmdq1->data = cmdq;
@ -60,11 +60,12 @@ cmd_source_file_exec(struct cmd *self, struct cmd_q *cmdq)
free(cause);
return (CMD_RETURN_ERROR);
}
ARRAY_ADD(&cfg_causes, cause);
cfg_add_cause("%s", cause);
free(cause);
/* FALLTHROUGH */
case 0:
if (cfg_references == 0)
cmd_source_file_show(cmdq);
cfg_print_causes(cmdq);
cmdq_free(cmdq1);
return (CMD_RETURN_NORMAL);
}
@ -76,25 +77,14 @@ cmd_source_file_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_WAIT);
}
void
cmd_source_file_show(struct cmd_q *cmdq)
{
u_int i;
char *cause;
for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) {
cause = ARRAY_ITEM(&cfg_causes, i);
cmdq_print(cmdq, "%s", cause);
free(cause);
}
ARRAY_FREE(&cfg_causes);
}
void
cmd_source_file_done(struct cmd_q *cmdq1)
{
struct cmd_q *cmdq = cmdq1->data;
if (cmdq1->client_exit >= 0)
cmdq->client_exit = cmdq1->client_exit;
cmdq_free(cmdq1);
cfg_references--;
@ -103,6 +93,6 @@ cmd_source_file_done(struct cmd_q *cmdq1)
return;
if (cfg_references == 0)
cmd_source_file_show(cmdq);
cfg_print_causes(cmdq);
cmdq_continue(cmdq);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@ -18,7 +18,10 @@
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h"
@ -27,63 +30,73 @@
* Split a window (add a new pane).
*/
void cmd_split_window_key_binding(struct cmd *, int);
#define SPLIT_WINDOW_TEMPLATE "#{session_name}:#{window_index}.#{pane_index}"
enum cmd_retval cmd_split_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_split_window_entry = {
"split-window", "splitw",
"c:dF:l:hp:Pt:v", 0, 1,
"[-dhvP] [-c start-directory] [-F format] [-p percentage|-l size] "
CMD_TARGET_PANE_USAGE " [command]",
0,
cmd_split_window_key_binding,
NULL,
cmd_split_window_exec
};
.name = "split-window",
.alias = "splitw",
void
cmd_split_window_key_binding(struct cmd *self, int key)
{
self->args = args_create(0);
if (key == '%')
args_set(self->args, 'h', NULL);
}
.args = { "bc:dF:l:hp:Pt:v", 0, -1 },
.usage = "[-bdhvP] [-c start-directory] [-F format] "
"[-p percentage|-l size] " CMD_TARGET_PANE_USAGE " [command]",
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_split_window_exec
};
enum cmd_retval
cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct session *s;
struct winlink *wl;
struct window *w;
struct window_pane *wp, *new_wp = NULL;
struct environ env;
const char *cmd, *cwd, *shell;
char *cause, *new_cause;
struct session *s = cmdq->state.tflag.s;
struct winlink *wl = cmdq->state.tflag.wl;
struct window *w = wl->window;
struct window_pane *wp = cmdq->state.tflag.wp, *new_wp = NULL;
struct environ *env;
const char *cmd, *path, *shell, *template, *cwd, *to_free;
char **argv, *cause, *new_cause, *cp;
u_int hlimit;
int size, percentage;
int argc, size, percentage;
enum layout_type type;
struct layout_cell *lc;
const char *template;
struct client *c;
struct format_tree *ft;
char *cp;
struct environ_entry *envent;
if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL)
return (CMD_RETURN_ERROR);
w = wl->window;
server_unzoom_window(w);
environ_init(&env);
environ_copy(&global_environ, &env);
environ_copy(&s->environ, &env);
server_fill_environ(s, &env);
env = environ_create();
environ_copy(global_environ, env);
environ_copy(s->environ, env);
server_fill_environ(s, env);
if (args->argc == 0)
cmd = options_get_string(&s->options, "default-command");
if (args->argc == 0) {
cmd = options_get_string(s->options, "default-command");
if (cmd != NULL && *cmd != '\0') {
argc = 1;
argv = (char **)&cmd;
} else {
argc = 0;
argv = NULL;
}
} else {
argc = args->argc;
argv = args->argv;
}
to_free = NULL;
if (args_has(args, 'c')) {
ft = format_create(cmdq, 0);
format_defaults(ft, cmdq->state.c, s, NULL, NULL);
to_free = cwd = format_expand(ft, args_get(args, 'c'));
format_free(ft);
} else if (cmdq->client != NULL && cmdq->client->session == NULL)
cwd = cmdq->client->cwd;
else
cmd = args->argv[0];
cwd = cmd_get_default_path(cmdq, args_get(args, 'c'));
cwd = s->cwd;
type = LAYOUT_TOPBOTTOM;
if (args_has(args, 'h'))
@ -111,22 +124,32 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
else
size = (wp->sx * percentage) / 100;
}
hlimit = options_get_number(&s->options, "history-limit");
hlimit = options_get_number(s->options, "history-limit");
shell = options_get_string(&s->options, "default-shell");
shell = options_get_string(s->options, "default-shell");
if (*shell == '\0' || areshell(shell))
shell = _PATH_BSHELL;
if ((lc = layout_split_pane(wp, type, size, 0)) == NULL) {
lc = layout_split_pane(wp, type, size, args_has(args, 'b'));
if (lc == NULL) {
cause = xstrdup("pane too small");
goto error;
}
new_wp = window_add_pane(w, hlimit);
if (window_pane_spawn(
new_wp, cmd, shell, cwd, &env, s->tio, &cause) != 0)
goto error;
layout_assign_pane(lc, new_wp);
path = NULL;
if (cmdq->client != NULL && cmdq->client->session == NULL)
envent = environ_find(cmdq->client->environ, "PATH");
else
envent = environ_find(s->environ, "PATH");
if (envent != NULL)
path = envent->value;
if (window_pane_spawn(new_wp, argc, argv, path, shell, cwd, env,
s->tio, &cause) != 0)
goto error;
server_redraw_window(w);
if (!args_has(args, 'd')) {
@ -136,18 +159,14 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
} else
server_status_session(s);
environ_free(&env);
environ_free(env);
if (args_has(args, 'P')) {
if ((template = args_get(args, 'F')) == NULL)
template = SPLIT_WINDOW_TEMPLATE;
ft = format_create();
if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
format_client(ft, c);
format_session(ft, s);
format_winlink(ft, s, wl);
format_window_pane(ft, new_wp);
ft = format_create(cmdq, 0);
format_defaults(ft, cmdq->state.c, s, wl, new_wp);
cp = format_expand(ft, template);
cmdq_print(cmdq, "%s", cp);
@ -156,13 +175,21 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
format_free(ft);
}
notify_window_layout_changed(w);
if (to_free != NULL)
free((void *)to_free);
return (CMD_RETURN_NORMAL);
error:
environ_free(&env);
if (new_wp != NULL)
environ_free(env);
if (new_wp != NULL) {
layout_close_pane(new_wp);
window_remove_pane(w, new_wp);
}
cmdq_error(cmdq, "create pane failed: %s", cause);
free(cause);
if (to_free != NULL)
free((void *)to_free);
return (CMD_RETURN_ERROR);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@ -107,10 +107,11 @@ cmd_string_parse(const char *s, struct cmd_list **cmdlist, const char *file,
case ' ':
case '\t':
if (buf != NULL) {
buf = xrealloc(buf, 1, len + 1);
buf = xrealloc(buf, len + 1);
buf[len] = '\0';
argv = xrealloc(argv, argc + 1, sizeof *argv);
argv = xreallocarray(argv, argc + 1,
sizeof *argv);
argv[argc++] = buf;
buf = NULL;
@ -125,7 +126,7 @@ cmd_string_parse(const char *s, struct cmd_list **cmdlist, const char *file,
whitespace = argv[0] + strcspn(argv[0], " \t");
if (equals == NULL || equals > whitespace)
break;
environ_put(&global_environ, argv[0]);
environ_put(global_environ, argv[0]);
argc--;
memmove(argv, argv + 1, argc * (sizeof *argv));
}
@ -151,7 +152,7 @@ cmd_string_parse(const char *s, struct cmd_list **cmdlist, const char *file,
if (len >= SIZE_MAX - 2)
goto error;
buf = xrealloc(buf, 1, len + 1);
buf = xrealloc(buf, len + 1);
buf[len++] = ch;
break;
}
@ -179,7 +180,7 @@ cmd_string_copy(char **dst, char *src, size_t *len)
srclen = strlen(src);
*dst = xrealloc(*dst, 1, *len + srclen + 1);
*dst = xrealloc(*dst, *len + srclen + 1);
strlcpy(*dst + *len, src, srclen + 1);
*len += srclen;
@ -231,11 +232,11 @@ cmd_string_string(const char *s, size_t *p, char endch, int esc)
if (len >= SIZE_MAX - 2)
goto error;
buf = xrealloc(buf, 1, len + 1);
buf = xrealloc(buf, len + 1);
buf[len++] = ch;
}
buf = xrealloc(buf, 1, len + 1);
buf = xrealloc(buf, len + 1);
buf[len] = '\0';
return (buf);
@ -278,7 +279,7 @@ cmd_string_variable(const char *s, size_t *p)
return (t);
}
buf = xrealloc(buf, 1, len + 1);
buf = xrealloc(buf, len + 1);
buf[len++] = ch;
for (;;) {
@ -288,7 +289,7 @@ cmd_string_variable(const char *s, size_t *p)
else {
if (len >= SIZE_MAX - 3)
goto error;
buf = xrealloc(buf, 1, len + 1);
buf = xrealloc(buf, len + 1);
buf[len++] = ch;
}
}
@ -299,10 +300,10 @@ cmd_string_variable(const char *s, size_t *p)
if (ch != EOF && fch != '{')
cmd_string_ungetc(p); /* ch */
buf = xrealloc(buf, 1, len + 1);
buf = xrealloc(buf, len + 1);
buf[len] = '\0';
envent = environ_find(&global_environ, buf);
envent = environ_find(global_environ, buf);
free(buf);
if (envent == NULL)
return (xstrdup(""));
@ -318,26 +319,41 @@ cmd_string_expand_tilde(const char *s, size_t *p)
{
struct passwd *pw;
struct environ_entry *envent;
char *home, *path, *username;
char *home, *path, *user, *cp;
int last;
home = NULL;
if (cmd_string_getc(s, p) == '/') {
envent = environ_find(&global_environ, "HOME");
last = cmd_string_getc(s, p);
if (last == EOF || last == '/' || last == ' '|| last == '\t') {
envent = environ_find(global_environ, "HOME");
if (envent != NULL && *envent->value != '\0')
home = envent->value;
else if ((pw = getpwuid(getuid())) != NULL)
home = pw->pw_dir;
} else {
cmd_string_ungetc(p);
if ((username = cmd_string_string(s, p, '/', 0)) == NULL)
return (NULL);
if ((pw = getpwnam(username)) != NULL)
cp = user = xmalloc(strlen(s));
for (;;) {
last = cmd_string_getc(s, p);
if (last == EOF || last == '/' || last == ' '|| last == '\t')
break;
*cp++ = last;
}
*cp = '\0';
if ((pw = getpwnam(user)) != NULL)
home = pw->pw_dir;
free(username);
free(user);
}
if (home == NULL)
return (NULL);
xasprintf(&path, "%s/", home);
if (last != EOF)
xasprintf(&path, "%s%c", home, last);
else
xasprintf(&path, "%s", home);
return (path);
}

View File

@ -1,56 +0,0 @@
/* $Id$ */
/*
* 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 <stdlib.h>
#include <string.h>
#include "tmux.h"
/*
* Suspend client with SIGTSTP.
*/
enum cmd_retval cmd_suspend_client_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_suspend_client_entry = {
"suspend-client", "suspendc",
"t:", 0, 0,
CMD_TARGET_CLIENT_USAGE,
0,
NULL,
NULL,
cmd_suspend_client_exec
};
enum cmd_retval
cmd_suspend_client_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
if ((c = cmd_find_client(cmdq, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
tty_stop_tty(&c->tty);
c->flags |= CLIENT_SUSPENDED;
server_write_client(c, MSG_SUSPEND, NULL, 0);
return (CMD_RETURN_NORMAL);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@ -26,62 +26,51 @@
* Swap two panes.
*/
void cmd_swap_pane_key_binding(struct cmd *, int);
enum cmd_retval cmd_swap_pane_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_swap_pane_entry = {
"swap-pane", "swapp",
"dDs:t:U", 0, 0,
"[-dDU] " CMD_SRCDST_PANE_USAGE,
0,
cmd_swap_pane_key_binding,
NULL,
cmd_swap_pane_exec
};
.name = "swap-pane",
.alias = "swapp",
void
cmd_swap_pane_key_binding(struct cmd *self, int key)
{
self->args = args_create(0);
if (key == '{')
args_set(self->args, 'U', NULL);
else if (key == '}')
args_set(self->args, 'D', NULL);
}
.args = { "dDs:t:U", 0, 0 },
.usage = "[-dDU] " CMD_SRCDST_PANE_USAGE,
.sflag = CMD_PANE_MARKED,
.tflag = CMD_PANE,
.flags = 0,
.exec = cmd_swap_pane_exec
};
enum cmd_retval
cmd_swap_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
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_pane *tmp_wp, *src_wp, *dst_wp;
struct layout_cell *src_lc, *dst_lc;
u_int sx, sy, xoff, yoff;
dst_wl = cmd_find_pane(cmdq, args_get(args, 't'), NULL, &dst_wp);
if (dst_wl == NULL)
return (CMD_RETURN_ERROR);
dst_wl = cmdq->state.tflag.wl;
dst_w = dst_wl->window;
dst_wp = cmdq->state.tflag.wp;
src_wl = cmdq->state.sflag.wl;
src_w = src_wl->window;
src_wp = cmdq->state.sflag.wp;
server_unzoom_window(dst_w);
if (!args_has(args, 's')) {
if (args_has(self->args, 'D')) {
src_wl = dst_wl;
src_w = dst_w;
if (args_has(self->args, 'D')) {
src_wp = TAILQ_NEXT(dst_wp, entry);
if (src_wp == NULL)
src_wp = TAILQ_FIRST(&dst_w->panes);
} else if (args_has(self->args, 'U')) {
src_wp = TAILQ_PREV(dst_wp, window_panes, entry);
if (src_wp == NULL)
src_wp = TAILQ_LAST(&dst_w->panes, window_panes);
} else
return (CMD_RETURN_NORMAL);
} else {
src_wl = cmd_find_pane(cmdq, args_get(args, 's'), NULL, &src_wp);
if (src_wl == NULL)
return (CMD_RETURN_ERROR);
src_w = src_wl->window;
src_wp = TAILQ_NEXT(dst_wp, entry);
if (src_wp == NULL)
src_wp = TAILQ_FIRST(&dst_w->panes);
} else if (args_has(self->args, 'U')) {
src_wl = dst_wl;
src_w = dst_w;
src_wp = TAILQ_PREV(dst_wp, window_panes, entry);
if (src_wp == NULL)
src_wp = TAILQ_LAST(&dst_w->panes, window_panes);
}
server_unzoom_window(src_w);

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -29,13 +29,17 @@
enum cmd_retval cmd_swap_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_swap_window_entry = {
"swap-window", "swapw",
"ds:t:", 0, 0,
"[-d] " CMD_SRCDST_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_swap_window_exec
.name = "swap-window",
.alias = "swapw",
.args = { "ds:t:", 0, 0 },
.usage = "[-d] " CMD_SRCDST_WINDOW_USAGE,
.sflag = CMD_WINDOW_MARKED,
.tflag = CMD_WINDOW,
.flags = 0,
.exec = cmd_swap_window_exec
};
enum cmd_retval
@ -45,24 +49,21 @@ cmd_swap_window_exec(struct cmd *self, struct cmd_q *cmdq)
cmdq_error(cmdq, "swap window is not supported with tmate");
return (CMD_RETURN_ERROR);
#else
struct args *args = self->args;
const char *target_src, *target_dst;
struct session *src, *dst;
struct session_group *sg_src, *sg_dst;
struct winlink *wl_src, *wl_dst;
struct window *w;
target_src = args_get(args, 's');
if ((wl_src = cmd_find_window(cmdq, target_src, &src)) == NULL)
return (CMD_RETURN_ERROR);
target_dst = args_get(args, 't');
if ((wl_dst = cmd_find_window(cmdq, target_dst, &dst)) == NULL)
return (CMD_RETURN_ERROR);
wl_src = cmdq->state.sflag.wl;
src = cmdq->state.sflag.s;
sg_src = session_group_find(src);
wl_dst = cmdq->state.tflag.wl;
dst = cmdq->state.tflag.s;
sg_dst = session_group_find(dst);
if (src != dst &&
sg_src != NULL && sg_dst != NULL && sg_src == sg_dst) {
if (src != dst && sg_src != NULL && sg_dst != NULL &&
sg_src == sg_dst) {
cmdq_error(cmdq, "can't move window, sessions are grouped");
return (CMD_RETURN_ERROR);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -27,57 +27,50 @@
* Switch client to a different session.
*/
void cmd_switch_client_key_binding(struct cmd *, int);
enum cmd_retval cmd_switch_client_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_switch_client_entry = {
"switch-client", "switchc",
"lc:npt:r", 0, 0,
"[-lnpr] [-c target-client] [-t target-session]",
CMD_READONLY,
cmd_switch_client_key_binding,
NULL,
cmd_switch_client_exec
};
.name = "switch-client",
.alias = "switchc",
void
cmd_switch_client_key_binding(struct cmd *self, int key)
{
self->args = args_create(0);
switch (key) {
case '(':
args_set(self->args, 'p', NULL);
break;
case ')':
args_set(self->args, 'n', NULL);
break;
case 'L':
args_set(self->args, 'l', NULL);
break;
}
}
.args = { "lc:Enpt:rT:", 0, 0 },
.usage = "[-Elnpr] [-c target-client] [-t target-session] "
"[-T key-table]",
.cflag = CMD_CLIENT,
.tflag = CMD_SESSION_WITHPANE,
.flags = CMD_READONLY,
.exec = cmd_switch_client_exec
};
enum cmd_retval
cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct client *c;
struct session *s;
struct args *args = self->args;
struct cmd_state *state = &cmdq->state;
struct client *c = state->c;
struct session *s = cmdq->state.tflag.s;
struct window_pane *wp;
const char *tablename, *update;
struct key_table *table;
if ((c = cmd_find_client(cmdq, args_get(args, 'c'), 0)) == NULL)
return (CMD_RETURN_ERROR);
if (args_has(args, 'r'))
c->flags ^= CLIENT_READONLY;
if (args_has(args, 'r')) {
if (c->flags & CLIENT_READONLY) {
c->flags &= ~CLIENT_READONLY;
cmdq_info(cmdq, "made client writable");
} else {
c->flags |= CLIENT_READONLY;
cmdq_info(cmdq, "made client read-only");
tablename = args_get(args, 'T');
if (tablename != NULL) {
table = key_bindings_get_table(tablename, 0);
if (table == NULL) {
cmdq_error(cmdq, "table %s doesn't exist", tablename);
return (CMD_RETURN_ERROR);
}
table->references++;
key_bindings_unref_table(c->keytable);
c->keytable = table;
return (CMD_RETURN_NORMAL);
}
s = NULL;
if (args_has(args, 'n')) {
if ((s = session_next_session(c->session)) == NULL) {
cmdq_error(cmdq, "can't find next session");
@ -91,24 +84,42 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
} else if (args_has(args, 'l')) {
if (c->last_session != NULL && session_alive(c->last_session))
s = c->last_session;
else
s = NULL;
if (s == NULL) {
cmdq_error(cmdq, "can't find last session");
return (CMD_RETURN_ERROR);
}
} else
s = cmd_find_session(cmdq, args_get(args, 't'), 0);
if (s == NULL)
return (CMD_RETURN_ERROR);
if (cmdq->client == NULL)
return (CMD_RETURN_NORMAL);
if (c->session != NULL)
s = state->tflag.s;
if (state->tflag.wl != NULL) {
wp = state->tflag.wp;
if (wp != NULL)
window_set_active_pane(wp->window, wp);
session_set_current(s, state->tflag.wl);
}
}
if (c != NULL && !args_has(args, 'E')) {
update = options_get_string(s->options, "update-environment");
environ_update(update, c->environ, s->environ);
}
if (c->session != NULL && c->session != s)
c->last_session = c->session;
c->session = s;
session_update_activity(s);
server_client_set_key_table(c, NULL);
status_timer_start(c);
session_update_activity(s, NULL);
gettimeofday(&s->last_attached_time, NULL);
recalculate_sizes();
server_check_unattached();
server_redraw_client(c);
s->curw->flags &= ~WINLINK_ALERTFLAGS;
alerts_check_session(s);
return (CMD_RETURN_NORMAL);
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -26,65 +26,80 @@
* Unbind key from command.
*/
enum cmd_retval cmd_unbind_key_check(struct args *);
enum cmd_retval cmd_unbind_key_exec(struct cmd *, struct cmd_q *);
enum cmd_retval cmd_unbind_key_table(struct cmd *, struct cmd_q *, int);
enum cmd_retval cmd_unbind_key_exec(struct cmd *, struct cmd_q *);
enum cmd_retval cmd_unbind_key_mode_table(struct cmd *, struct cmd_q *,
key_code);
const struct cmd_entry cmd_unbind_key_entry = {
"unbind-key", "unbind",
"acnt:", 0, 1,
"[-acn] [-t key-table] key",
0,
NULL,
cmd_unbind_key_check,
cmd_unbind_key_exec
};
.name = "unbind-key",
.alias = "unbind",
enum cmd_retval
cmd_unbind_key_check(struct args *args)
{
if (args_has(args, 'a') && args->argc != 0)
return (CMD_RETURN_ERROR);
if (!args_has(args, 'a') && args->argc != 1)
return (CMD_RETURN_ERROR);
return (CMD_RETURN_NORMAL);
}
.args = { "acnt:T:", 0, 1 },
.usage = "[-acn] [-t mode-table] [-T key-table] key",
.flags = 0,
.exec = cmd_unbind_key_exec
};
enum cmd_retval
cmd_unbind_key_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
struct key_binding *bd;
int key;
struct args *args = self->args;
key_code key;
const char *tablename;
if (!args_has(args, 'a')) {
if (args->argc != 1) {
cmdq_error(cmdq, "missing key");
return (CMD_RETURN_ERROR);
}
key = key_string_lookup_string(args->argv[0]);
if (key == KEYC_NONE) {
if (key == KEYC_NONE || key == KEYC_UNKNOWN) {
cmdq_error(cmdq, "unknown key: %s", args->argv[0]);
return (CMD_RETURN_ERROR);
}
} else
key = KEYC_NONE;
} else {
if (args->argc != 0) {
cmdq_error(cmdq, "key given with -a");
return (CMD_RETURN_ERROR);
}
key = KEYC_UNKNOWN;
}
if (args_has(args, 't'))
return (cmd_unbind_key_table(self, cmdq, key));
return (cmd_unbind_key_mode_table(self, cmdq, key));
if (key == KEYC_NONE) {
while (!RB_EMPTY(&key_bindings)) {
bd = RB_ROOT(&key_bindings);
key_bindings_remove(bd->key);
if (key == KEYC_UNKNOWN) {
tablename = args_get(args, 'T');
if (tablename == NULL) {
key_bindings_remove_table("root");
key_bindings_remove_table("prefix");
return (CMD_RETURN_NORMAL);
}
if (key_bindings_get_table(tablename, 0) == NULL) {
cmdq_error(cmdq, "table %s doesn't exist", tablename);
return (CMD_RETURN_ERROR);
}
key_bindings_remove_table(tablename);
return (CMD_RETURN_NORMAL);
}
if (!args_has(args, 'n'))
key |= KEYC_PREFIX;
key_bindings_remove(key);
if (args_has(args, 'T')) {
tablename = args_get(args, 'T');
if (key_bindings_get_table(tablename, 0) == NULL) {
cmdq_error(cmdq, "table %s doesn't exist", tablename);
return (CMD_RETURN_ERROR);
}
} else if (args_has(args, 'n'))
tablename = "root";
else
tablename = "prefix";
key_bindings_remove(tablename, key);
return (CMD_RETURN_NORMAL);
}
enum cmd_retval
cmd_unbind_key_table(struct cmd *self, struct cmd_q *cmdq, int key)
cmd_unbind_key_mode_table(struct cmd *self, struct cmd_q *cmdq, key_code key)
{
struct args *args = self->args;
const char *tablename;
@ -97,7 +112,7 @@ cmd_unbind_key_table(struct cmd *self, struct cmd_q *cmdq, int key)
return (CMD_RETURN_ERROR);
}
if (key == KEYC_NONE) {
if (key == KEYC_UNKNOWN) {
while (!RB_EMPTY(mtab->tree)) {
mbind = RB_ROOT(mtab->tree);
RB_REMOVE(mode_key_tree, mtab->tree, mbind);

View File

@ -1,75 +0,0 @@
/* $Id$ */
/*
* 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"
/*
* Unlink a window, unless it would be destroyed by doing so (only one link).
*/
enum cmd_retval cmd_unlink_window_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_unlink_window_entry = {
"unlink-window", "unlinkw",
"kt:", 0, 0,
"[-k] " CMD_TARGET_WINDOW_USAGE,
0,
NULL,
NULL,
cmd_unlink_window_exec
};
enum cmd_retval
cmd_unlink_window_exec(struct cmd *self, struct cmd_q *cmdq)
{
#ifdef TMATE
cmdq_error(cmdq, "unlink window is not supported with tmate");
return (CMD_RETURN_ERROR);
#else
struct args *args = self->args;
struct winlink *wl;
struct window *w;
struct session *s, *s2;
struct session_group *sg;
u_int references;
if ((wl = cmd_find_window(cmdq, args_get(args, 't'), &s)) == NULL)
return (CMD_RETURN_ERROR);
w = wl->window;
sg = session_group_find(s);
if (sg != NULL) {
references = 0;
TAILQ_FOREACH(s2, &sg->sessions, gentry)
references++;
} else
references = 1;
if (!args_has(self->args, 'k') && w->references == references) {
cmdq_error(cmdq, "window is only linked to one session");
return (CMD_RETURN_ERROR);
}
server_unlink_window(s, wl);
recalculate_sizes();
return (CMD_RETURN_NORMAL);
#endif
}

View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2013 Nicholas Marriott <nicm@users.sourceforge.net>
@ -32,18 +32,20 @@
enum cmd_retval cmd_wait_for_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_wait_for_entry = {
"wait-for", "wait",
"LSU", 1, 1,
"[-LSU] channel",
0,
NULL,
NULL,
cmd_wait_for_exec
.name = "wait-for",
.alias = "wait",
.args = { "LSU", 1, 1 },
.usage = "[-L|-S|-U] channel",
.flags = 0,
.exec = cmd_wait_for_exec
};
struct wait_channel {
const char *name;
int locked;
int woken;
TAILQ_HEAD(, cmd_q) waiters;
TAILQ_HEAD(, cmd_q) lockers;
@ -72,6 +74,46 @@ enum cmd_retval cmd_wait_for_lock(struct cmd_q *, const char *,
enum cmd_retval cmd_wait_for_unlock(struct cmd_q *, const char *,
struct wait_channel *);
struct wait_channel *cmd_wait_for_add(const char *);
void cmd_wait_for_remove(struct wait_channel *wc);
struct wait_channel *
cmd_wait_for_add(const char *name)
{
struct wait_channel *wc;
wc = xmalloc(sizeof *wc);
wc->name = xstrdup(name);
wc->locked = 0;
wc->woken = 0;
TAILQ_INIT(&wc->waiters);
TAILQ_INIT(&wc->lockers);
RB_INSERT(wait_channels, &wait_channels, wc);
log_debug("add wait channel %s", wc->name);
return (wc);
}
void
cmd_wait_for_remove(struct wait_channel *wc)
{
if (wc->locked)
return;
if (!TAILQ_EMPTY(&wc->waiters) || !wc->woken)
return;
log_debug("remove wait channel %s", wc->name);
RB_REMOVE(wait_channels, &wait_channels, wc);
free((void *)wc->name);
free(wc);
}
enum cmd_retval
cmd_wait_for_exec(struct cmd *self, struct cmd_q *cmdq)
{
@ -92,15 +134,20 @@ cmd_wait_for_exec(struct cmd *self, struct cmd_q *cmdq)
}
enum cmd_retval
cmd_wait_for_signal(struct cmd_q *cmdq, const char *name,
cmd_wait_for_signal(__unused struct cmd_q *cmdq, const char *name,
struct wait_channel *wc)
{
struct cmd_q *wq, *wq1;
if (wc == NULL || TAILQ_EMPTY(&wc->waiters)) {
cmdq_error(cmdq, "no waiting clients on %s", name);
return (CMD_RETURN_ERROR);
if (wc == NULL)
wc = cmd_wait_for_add(name);
if (TAILQ_EMPTY(&wc->waiters) && !wc->woken) {
log_debug("signal wait channel %s, no waiters", wc->name);
wc->woken = 1;
return (CMD_RETURN_NORMAL);
}
log_debug("signal wait channel %s, with waiters", wc->name);
TAILQ_FOREACH_SAFE(wq, &wc->waiters, waitentry, wq1) {
TAILQ_REMOVE(&wc->waiters, wq, waitentry);
@ -108,12 +155,7 @@ cmd_wait_for_signal(struct cmd_q *cmdq, const char *name,
cmdq_continue(wq);
}
if (!wc->locked) {
RB_REMOVE(wait_channels, &wait_channels, wc);
free((void*) wc->name);
free(wc);
}
cmd_wait_for_remove(wc);
return (CMD_RETURN_NORMAL);
}
@ -148,26 +190,27 @@ enum cmd_retval
cmd_wait_for_wait(struct cmd_q *cmdq, const char *name,
struct wait_channel *wc)
{
struct client *c = cmdq->client;
#ifdef TMATE
if (!strcmp(name, "tmate-ready") && tmate_session.decoder.ready)
return (CMD_RETURN_NORMAL);
#endif
if (cmdq->client == NULL || cmdq->client->session != NULL) {
if (c == NULL || c->session != NULL) {
cmdq_error(cmdq, "not able to wait");
return (CMD_RETURN_ERROR);
}
if (wc == NULL) {
wc = xmalloc(sizeof *wc);
wc->name = xstrdup(name);
wc->locked = 0;
TAILQ_INIT(&wc->waiters);
TAILQ_INIT(&wc->lockers);
RB_INSERT(wait_channels, &wait_channels, wc);
if (wc == NULL)
wc = cmd_wait_for_add(name);
if (wc->woken) {
log_debug("wait channel %s already woken (%p)", wc->name, c);
cmd_wait_for_remove(wc);
return (CMD_RETURN_NORMAL);
}
log_debug("wait channel %s not woken (%p)", wc->name, c);
TAILQ_INSERT_TAIL(&wc->waiters, cmdq, waitentry);
cmdq->references++;
@ -184,14 +227,8 @@ cmd_wait_for_lock(struct cmd_q *cmdq, const char *name,
return (CMD_RETURN_ERROR);
}
if (wc == NULL) {
wc = xmalloc(sizeof *wc);
wc->name = xstrdup(name);
wc->locked = 0;
TAILQ_INIT(&wc->waiters);
TAILQ_INIT(&wc->lockers);
RB_INSERT(wait_channels, &wait_channels, wc);
}
if (wc == NULL)
wc = cmd_wait_for_add(name);
if (wc->locked) {
TAILQ_INSERT_TAIL(&wc->lockers, cmdq, waitentry);
@ -220,13 +257,31 @@ cmd_wait_for_unlock(struct cmd_q *cmdq, const char *name,
cmdq_continue(wq);
} else {
wc->locked = 0;
if (TAILQ_EMPTY(&wc->waiters)) {
RB_REMOVE(wait_channels, &wait_channels, wc);
free((void*) wc->name);
free(wc);
}
cmd_wait_for_remove(wc);
}
return (CMD_RETURN_NORMAL);
}
void
cmd_wait_for_flush(void)
{
struct wait_channel *wc, *wc1;
struct cmd_q *wq, *wq1;
RB_FOREACH_SAFE(wc, wait_channels, &wait_channels, wc1) {
TAILQ_FOREACH_SAFE(wq, &wc->waiters, waitentry, wq1) {
TAILQ_REMOVE(&wc->waiters, wq, waitentry);
if (!cmdq_free(wq))
cmdq_continue(wq);
}
wc->woken = 1;
TAILQ_FOREACH_SAFE(wq, &wc->lockers, waitentry, wq1) {
TAILQ_REMOVE(&wc->lockers, wq, waitentry);
if (!cmdq_free(wq))
cmdq_continue(wq);
}
wc->locked = 0;
cmd_wait_for_remove(wc);
}
}

1331
cmd.c

File diff suppressed because it is too large Load Diff

422
colour.c
View File

@ -1,4 +1,4 @@
/* $Id$ */
/* $OpenBSD$ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@ -29,91 +29,305 @@
* of the 256 colour palette.
*/
/* An RGB colour. */
struct colour_rgb {
u_char i;
u_char r;
u_char g;
u_char b;
};
/* 256 colour RGB table, generated on first use. */
struct colour_rgb *colour_rgb_256;
const struct colour_rgb colour_from_256[] = {
{ 0, 0x00, 0x00, 0x00 }, { 1, 0x00, 0x00, 0x5f },
{ 2, 0x00, 0x00, 0x87 }, { 3, 0x00, 0x00, 0xaf },
{ 4, 0x00, 0x00, 0xd7 }, { 5, 0x00, 0x00, 0xff },
{ 6, 0x00, 0x5f, 0x00 }, { 7, 0x00, 0x5f, 0x5f },
{ 8, 0x00, 0x5f, 0x87 }, { 9, 0x00, 0x5f, 0xaf },
{ 10, 0x00, 0x5f, 0xd7 }, { 11, 0x00, 0x5f, 0xff },
{ 12, 0x00, 0x87, 0x00 }, { 13, 0x00, 0x87, 0x5f },
{ 14, 0x00, 0x87, 0x87 }, { 15, 0x00, 0x87, 0xaf },
{ 16, 0x00, 0x87, 0xd7 }, { 17, 0x00, 0x87, 0xff },
{ 18, 0x00, 0xaf, 0x00 }, { 19, 0x00, 0xaf, 0x5f },
{ 20, 0x00, 0xaf, 0x87 }, { 21, 0x00, 0xaf, 0xaf },
{ 22, 0x00, 0xaf, 0xd7 }, { 23, 0x00, 0xaf, 0xff },
{ 24, 0x00, 0xd7, 0x00 }, { 25, 0x00, 0xd7, 0x5f },
{ 26, 0x00, 0xd7, 0x87 }, { 27, 0x00, 0xd7, 0xaf },
{ 28, 0x00, 0xd7, 0xd7 }, { 29, 0x00, 0xd7, 0xff },
{ 30, 0x00, 0xff, 0x00 }, { 31, 0x00, 0xff, 0x5f },
{ 32, 0x00, 0xff, 0x87 }, { 33, 0x00, 0xff, 0xaf },
{ 34, 0x00, 0xff, 0xd7 }, { 35, 0x00, 0xff, 0xff },
{ 36, 0x5f, 0x00, 0x00 }, { 37, 0x5f, 0x00, 0x5f },
{ 38, 0x5f, 0x00, 0x87 }, { 39, 0x5f, 0x00, 0xaf },
{ 40, 0x5f, 0x00, 0xd7 }, { 41, 0x5f, 0x00, 0xff },
{ 42, 0x5f, 0x5f, 0x00 }, { 43, 0x5f, 0x5f, 0x5f },
{ 44, 0x5f, 0x5f, 0x87 }, { 45, 0x5f, 0x5f, 0xaf },
{ 46, 0x5f, 0x5f, 0xd7 }, { 47, 0x5f, 0x5f, 0xff },
{ 48, 0x5f, 0x87, 0x00 }, { 49, 0x5f, 0x87, 0x5f },
{ 50, 0x5f, 0x87, 0x87 }, { 51, 0x5f, 0x87, 0xaf },
{ 52, 0x5f, 0x87, 0xd7 }, { 53, 0x5f, 0x87, 0xff },
{ 54, 0x5f, 0xaf, 0x00 }, { 55, 0x5f, 0xaf, 0x5f },
{ 56, 0x5f, 0xaf, 0x87 }, { 57, 0x5f, 0xaf, 0xaf },
{ 58, 0x5f, 0xaf, 0xd7 }, { 59, 0x5f, 0xaf, 0xff },
{ 60, 0x5f, 0xd7, 0x00 }, { 61, 0x5f, 0xd7, 0x5f },
{ 62, 0x5f, 0xd7, 0x87 }, { 63, 0x5f, 0xd7, 0xaf },
{ 64, 0x5f, 0xd7, 0xd7 }, { 65, 0x5f, 0xd7, 0xff },
{ 66, 0x5f, 0xff, 0x00 }, { 67, 0x5f, 0xff, 0x5f },
{ 68, 0x5f, 0xff, 0x87 }, { 69, 0x5f, 0xff, 0xaf },
{ 70, 0x5f, 0xff, 0xd7 }, { 71, 0x5f, 0xff, 0xff },
{ 72, 0x87, 0x00, 0x00 }, { 73, 0x87, 0x00, 0x5f },
{ 74, 0x87, 0x00, 0x87 }, { 75, 0x87, 0x00, 0xaf },
{ 76, 0x87, 0x00, 0xd7 }, { 77, 0x87, 0x00, 0xff },
{ 78, 0x87, 0x5f, 0x00 }, { 79, 0x87, 0x5f, 0x5f },
{ 80, 0x87, 0x5f, 0x87 }, { 81, 0x87, 0x5f, 0xaf },
{ 82, 0x87, 0x5f, 0xd7 }, { 83, 0x87, 0x5f, 0xff },
{ 84, 0x87, 0x87, 0x00 }, { 85, 0x87, 0x87, 0x5f },
{ 86, 0x87, 0x87, 0x87 }, { 87, 0x87, 0x87, 0xaf },
{ 88, 0x87, 0x87, 0xd7 }, { 89, 0x87, 0x87, 0xff },
{ 90, 0x87, 0xaf, 0x00 }, { 91, 0x87, 0xaf, 0x5f },
{ 92, 0x87, 0xaf, 0x87 }, { 93, 0x87, 0xaf, 0xaf },
{ 94, 0x87, 0xaf, 0xd7 }, { 95, 0x87, 0xaf, 0xff },
{ 96, 0x87, 0xd7, 0x00 }, { 97, 0x87, 0xd7, 0x5f },
{ 98, 0x87, 0xd7, 0x87 }, { 99, 0x87, 0xd7, 0xaf },
{ 100, 0x87, 0xd7, 0xd7 }, { 101, 0x87, 0xd7, 0xff },
{ 102, 0x87, 0xff, 0x00 }, { 103, 0x87, 0xff, 0x5f },
{ 104, 0x87, 0xff, 0x87 }, { 105, 0x87, 0xff, 0xaf },
{ 106, 0x87, 0xff, 0xd7 }, { 107, 0x87, 0xff, 0xff },
{ 108, 0xaf, 0x00, 0x00 }, { 109, 0xaf, 0x00, 0x5f },
{ 110, 0xaf, 0x00, 0x87 }, { 111, 0xaf, 0x00, 0xaf },
{ 112, 0xaf, 0x00, 0xd7 }, { 113, 0xaf, 0x00, 0xff },
{ 114, 0xaf, 0x5f, 0x00 }, { 115, 0xaf, 0x5f, 0x5f },
{ 116, 0xaf, 0x5f, 0x87 }, { 117, 0xaf, 0x5f, 0xaf },
{ 118, 0xaf, 0x5f, 0xd7 }, { 119, 0xaf, 0x5f, 0xff },
{ 120, 0xaf, 0x87, 0x00 }, { 121, 0xaf, 0x87, 0x5f },
{ 122, 0xaf, 0x87, 0x87 }, { 123, 0xaf, 0x87, 0xaf },
{ 124, 0xaf, 0x87, 0xd7 }, { 125, 0xaf, 0x87, 0xff },
{ 126, 0xaf, 0xaf, 0x00 }, { 127, 0xaf, 0xaf, 0x5f },
{ 128, 0xaf, 0xaf, 0x87 }, { 129, 0xaf, 0xaf, 0xaf },
{ 130, 0xaf, 0xaf, 0xd7 }, { 131, 0xaf, 0xaf, 0xff },
{ 132, 0xaf, 0xd7, 0x00 }, { 133, 0xaf, 0xd7, 0x5f },
{ 134, 0xaf, 0xd7, 0x87 }, { 135, 0xaf, 0xd7, 0xaf },
{ 136, 0xaf, 0xd7, 0xd7 }, { 137, 0xaf, 0xd7, 0xff },
{ 138, 0xaf, 0xff, 0x00 }, { 139, 0xaf, 0xff, 0x5f },
{ 140, 0xaf, 0xff, 0x87 }, { 141, 0xaf, 0xff, 0xaf },
{ 142, 0xaf, 0xff, 0xd7 }, { 143, 0xaf, 0xff, 0xff },
{ 144, 0xd7, 0x00, 0x00 }, { 145, 0xd7, 0x00, 0x5f },
{ 146, 0xd7, 0x00, 0x87 }, { 147, 0xd7, 0x00, 0xaf },
{ 148, 0xd7, 0x00, 0xd7 }, { 149, 0xd7, 0x00, 0xff },
{ 150, 0xd7, 0x5f, 0x00 }, { 151, 0xd7, 0x5f, 0x5f },
{ 152, 0xd7, 0x5f, 0x87 }, { 153, 0xd7, 0x5f, 0xaf },
{ 154, 0xd7, 0x5f, 0xd7 }, { 155, 0xd7, 0x5f, 0xff },
{ 156, 0xd7, 0x87, 0x00 }, { 157, 0xd7, 0x87, 0x5f },
{ 158, 0xd7, 0x87, 0x87 }, { 159, 0xd7, 0x87, 0xaf },
{ 160, 0xd7, 0x87, 0xd7 }, { 161, 0xd7, 0x87, 0xff },
{ 162, 0xd7, 0xaf, 0x00 }, { 163, 0xd7, 0xaf, 0x5f },
{ 164, 0xd7, 0xaf, 0x87 }, { 165, 0xd7, 0xaf, 0xaf },
{ 166, 0xd7, 0xaf, 0xd7 }, { 167, 0xd7, 0xaf, 0xff },
{ 168, 0xd7, 0xd7, 0x00 }, { 169, 0xd7, 0xd7, 0x5f },
{ 170, 0xd7, 0xd7, 0x87 }, { 171, 0xd7, 0xd7, 0xaf },
{ 172, 0xd7, 0xd7, 0xd7 }, { 173, 0xd7, 0xd7, 0xff },
{ 174, 0xd7, 0xff, 0x00 }, { 175, 0xd7, 0xff, 0x5f },
{ 176, 0xd7, 0xff, 0x87 }, { 177, 0xd7, 0xff, 0xaf },
{ 178, 0xd7, 0xff, 0xd7 }, { 179, 0xd7, 0xff, 0xff },
{ 180, 0xff, 0x00, 0x00 }, { 181, 0xff, 0x00, 0x5f },
{ 182, 0xff, 0x00, 0x87 }, { 183, 0xff, 0x00, 0xaf },
{ 184, 0xff, 0x00, 0xd7 }, { 185, 0xff, 0x00, 0xff },
{ 186, 0xff, 0x5f, 0x00 }, { 187, 0xff, 0x5f, 0x5f },
{ 188, 0xff, 0x5f, 0x87 }, { 189, 0xff, 0x5f, 0xaf },
{ 190, 0xff, 0x5f, 0xd7 }, { 191, 0xff, 0x5f, 0xff },
{ 192, 0xff, 0x87, 0x00 }, { 193, 0xff, 0x87, 0x5f },
{ 194, 0xff, 0x87, 0x87 }, { 195, 0xff, 0x87, 0xaf },
{ 196, 0xff, 0x87, 0xd7 }, { 197, 0xff, 0x87, 0xff },
{ 198, 0xff, 0xaf, 0x00 }, { 199, 0xff, 0xaf, 0x5f },
{ 200, 0xff, 0xaf, 0x87 }, { 201, 0xff, 0xaf, 0xaf },
{ 202, 0xff, 0xaf, 0xd7 }, { 203, 0xff, 0xaf, 0xff },
{ 204, 0xff, 0xd7, 0x00 }, { 205, 0xff, 0xd7, 0x5f },
{ 206, 0xff, 0xd7, 0x87 }, { 207, 0xff, 0xd7, 0xaf },
{ 208, 0xff, 0xd7, 0xd7 }, { 209, 0xff, 0xd7, 0xff },
{ 210, 0xff, 0xff, 0x00 }, { 211, 0xff, 0xff, 0x5f },
{ 212, 0xff, 0xff, 0x87 }, { 213, 0xff, 0xff, 0xaf },
{ 214, 0xff, 0xff, 0xd7 }, { 215, 0xff, 0xff, 0xff },
{ 216, 0x08, 0x08, 0x08 }, { 217, 0x12, 0x12, 0x12 },
{ 218, 0x1c, 0x1c, 0x1c }, { 219, 0x26, 0x26, 0x26 },
{ 220, 0x30, 0x30, 0x30 }, { 221, 0x3a, 0x3a, 0x3a },
{ 222, 0x44, 0x44, 0x44 }, { 223, 0x4e, 0x4e, 0x4e },
{ 224, 0x58, 0x58, 0x58 }, { 225, 0x62, 0x62, 0x62 },
{ 226, 0x6c, 0x6c, 0x6c }, { 227, 0x76, 0x76, 0x76 },
{ 228, 0x80, 0x80, 0x80 }, { 229, 0x8a, 0x8a, 0x8a },
{ 230, 0x94, 0x94, 0x94 }, { 231, 0x9e, 0x9e, 0x9e },
{ 232, 0xa8, 0xa8, 0xa8 }, { 233, 0xb2, 0xb2, 0xb2 },
{ 234, 0xbc, 0xbc, 0xbc }, { 235, 0xc6, 0xc6, 0xc6 },
{ 236, 0xd0, 0xd0, 0xd0 }, { 237, 0xda, 0xda, 0xda },
{ 238, 0xe4, 0xe4, 0xe4 }, { 239, 0xee, 0xee, 0xee },
};
const struct colour_rgb colour_to_256[] = {
{ 0, 0x00, 0x00, 0x00 }, { 1, 0x00, 0x00, 0x5f },
{ 2, 0x00, 0x00, 0x87 }, { 3, 0x00, 0x00, 0xaf },
{ 4, 0x00, 0x00, 0xd7 }, { 5, 0x00, 0x00, 0xff },
{ 6, 0x00, 0x5f, 0x00 }, { 7, 0x00, 0x5f, 0x5f },
{ 8, 0x00, 0x5f, 0x87 }, { 9, 0x00, 0x5f, 0xaf },
{ 10, 0x00, 0x5f, 0xd7 }, { 11, 0x00, 0x5f, 0xff },
{ 12, 0x00, 0x87, 0x00 }, { 13, 0x00, 0x87, 0x5f },
{ 14, 0x00, 0x87, 0x87 }, { 15, 0x00, 0x87, 0xaf },
{ 16, 0x00, 0x87, 0xd7 }, { 17, 0x00, 0x87, 0xff },
{ 18, 0x00, 0xaf, 0x00 }, { 19, 0x00, 0xaf, 0x5f },
{ 20, 0x00, 0xaf, 0x87 }, { 21, 0x00, 0xaf, 0xaf },
{ 22, 0x00, 0xaf, 0xd7 }, { 23, 0x00, 0xaf, 0xff },
{ 24, 0x00, 0xd7, 0x00 }, { 25, 0x00, 0xd7, 0x5f },
{ 26, 0x00, 0xd7, 0x87 }, { 27, 0x00, 0xd7, 0xaf },
{ 28, 0x00, 0xd7, 0xd7 }, { 29, 0x00, 0xd7, 0xff },
{ 30, 0x00, 0xff, 0x00 }, { 31, 0x00, 0xff, 0x5f },
{ 32, 0x00, 0xff, 0x87 }, { 33, 0x00, 0xff, 0xaf },
{ 34, 0x00, 0xff, 0xd7 }, { 35, 0x00, 0xff, 0xff },
{ 216, 0x08, 0x08, 0x08 }, { 217, 0x12, 0x12, 0x12 },
{ 218, 0x1c, 0x1c, 0x1c }, { 219, 0x26, 0x26, 0x26 },
{ 220, 0x30, 0x30, 0x30 }, { 221, 0x3a, 0x3a, 0x3a },
{ 222, 0x44, 0x44, 0x44 }, { 223, 0x4e, 0x4e, 0x4e },
{ 224, 0x58, 0x58, 0x58 }, { 36, 0x5f, 0x00, 0x00 },
{ 37, 0x5f, 0x00, 0x5f }, { 38, 0x5f, 0x00, 0x87 },
{ 39, 0x5f, 0x00, 0xaf }, { 40, 0x5f, 0x00, 0xd7 },
{ 41, 0x5f, 0x00, 0xff }, { 42, 0x5f, 0x5f, 0x00 },
{ 43, 0x5f, 0x5f, 0x5f }, { 44, 0x5f, 0x5f, 0x87 },
{ 45, 0x5f, 0x5f, 0xaf }, { 46, 0x5f, 0x5f, 0xd7 },
{ 47, 0x5f, 0x5f, 0xff }, { 48, 0x5f, 0x87, 0x00 },
{ 49, 0x5f, 0x87, 0x5f }, { 50, 0x5f, 0x87, 0x87 },
{ 51, 0x5f, 0x87, 0xaf }, { 52, 0x5f, 0x87, 0xd7 },
{ 53, 0x5f, 0x87, 0xff }, { 54, 0x5f, 0xaf, 0x00 },
{ 55, 0x5f, 0xaf, 0x5f }, { 56, 0x5f, 0xaf, 0x87 },
{ 57, 0x5f, 0xaf, 0xaf }, { 58, 0x5f, 0xaf, 0xd7 },
{ 59, 0x5f, 0xaf, 0xff }, { 60, 0x5f, 0xd7, 0x00 },
{ 61, 0x5f, 0xd7, 0x5f }, { 62, 0x5f, 0xd7, 0x87 },
{ 63, 0x5f, 0xd7, 0xaf }, { 64, 0x5f, 0xd7, 0xd7 },
{ 65, 0x5f, 0xd7, 0xff }, { 66, 0x5f, 0xff, 0x00 },
{ 67, 0x5f, 0xff, 0x5f }, { 68, 0x5f, 0xff, 0x87 },
{ 69, 0x5f, 0xff, 0xaf }, { 70, 0x5f, 0xff, 0xd7 },
{ 71, 0x5f, 0xff, 0xff }, { 225, 0x62, 0x62, 0x62 },
{ 226, 0x6c, 0x6c, 0x6c }, { 227, 0x76, 0x76, 0x76 },
{ 228, 0x80, 0x80, 0x80 }, { 72, 0x87, 0x00, 0x00 },
{ 73, 0x87, 0x00, 0x5f }, { 74, 0x87, 0x00, 0x87 },
{ 75, 0x87, 0x00, 0xaf }, { 76, 0x87, 0x00, 0xd7 },
{ 77, 0x87, 0x00, 0xff }, { 78, 0x87, 0x5f, 0x00 },
{ 79, 0x87, 0x5f, 0x5f }, { 80, 0x87, 0x5f, 0x87 },
{ 81, 0x87, 0x5f, 0xaf }, { 82, 0x87, 0x5f, 0xd7 },
{ 83, 0x87, 0x5f, 0xff }, { 84, 0x87, 0x87, 0x00 },
{ 85, 0x87, 0x87, 0x5f }, { 86, 0x87, 0x87, 0x87 },
{ 87, 0x87, 0x87, 0xaf }, { 88, 0x87, 0x87, 0xd7 },
{ 89, 0x87, 0x87, 0xff }, { 90, 0x87, 0xaf, 0x00 },
{ 91, 0x87, 0xaf, 0x5f }, { 92, 0x87, 0xaf, 0x87 },
{ 93, 0x87, 0xaf, 0xaf }, { 94, 0x87, 0xaf, 0xd7 },
{ 95, 0x87, 0xaf, 0xff }, { 96, 0x87, 0xd7, 0x00 },
{ 97, 0x87, 0xd7, 0x5f }, { 98, 0x87, 0xd7, 0x87 },
{ 99, 0x87, 0xd7, 0xaf }, { 100, 0x87, 0xd7, 0xd7 },
{ 101, 0x87, 0xd7, 0xff }, { 102, 0x87, 0xff, 0x00 },
{ 103, 0x87, 0xff, 0x5f }, { 104, 0x87, 0xff, 0x87 },
{ 105, 0x87, 0xff, 0xaf }, { 106, 0x87, 0xff, 0xd7 },
{ 107, 0x87, 0xff, 0xff }, { 229, 0x8a, 0x8a, 0x8a },
{ 230, 0x94, 0x94, 0x94 }, { 231, 0x9e, 0x9e, 0x9e },
{ 232, 0xa8, 0xa8, 0xa8 }, { 108, 0xaf, 0x00, 0x00 },
{ 109, 0xaf, 0x00, 0x5f }, { 110, 0xaf, 0x00, 0x87 },
{ 111, 0xaf, 0x00, 0xaf }, { 112, 0xaf, 0x00, 0xd7 },
{ 113, 0xaf, 0x00, 0xff }, { 114, 0xaf, 0x5f, 0x00 },
{ 115, 0xaf, 0x5f, 0x5f }, { 116, 0xaf, 0x5f, 0x87 },
{ 117, 0xaf, 0x5f, 0xaf }, { 118, 0xaf, 0x5f, 0xd7 },
{ 119, 0xaf, 0x5f, 0xff }, { 120, 0xaf, 0x87, 0x00 },
{ 121, 0xaf, 0x87, 0x5f }, { 122, 0xaf, 0x87, 0x87 },
{ 123, 0xaf, 0x87, 0xaf }, { 124, 0xaf, 0x87, 0xd7 },
{ 125, 0xaf, 0x87, 0xff }, { 126, 0xaf, 0xaf, 0x00 },
{ 127, 0xaf, 0xaf, 0x5f }, { 128, 0xaf, 0xaf, 0x87 },
{ 129, 0xaf, 0xaf, 0xaf }, { 130, 0xaf, 0xaf, 0xd7 },
{ 131, 0xaf, 0xaf, 0xff }, { 132, 0xaf, 0xd7, 0x00 },
{ 133, 0xaf, 0xd7, 0x5f }, { 134, 0xaf, 0xd7, 0x87 },
{ 135, 0xaf, 0xd7, 0xaf }, { 136, 0xaf, 0xd7, 0xd7 },
{ 137, 0xaf, 0xd7, 0xff }, { 138, 0xaf, 0xff, 0x00 },
{ 139, 0xaf, 0xff, 0x5f }, { 140, 0xaf, 0xff, 0x87 },
{ 141, 0xaf, 0xff, 0xaf }, { 142, 0xaf, 0xff, 0xd7 },
{ 143, 0xaf, 0xff, 0xff }, { 233, 0xb2, 0xb2, 0xb2 },
{ 234, 0xbc, 0xbc, 0xbc }, { 235, 0xc6, 0xc6, 0xc6 },
{ 236, 0xd0, 0xd0, 0xd0 }, { 144, 0xd7, 0x00, 0x00 },
{ 145, 0xd7, 0x00, 0x5f }, { 146, 0xd7, 0x00, 0x87 },
{ 147, 0xd7, 0x00, 0xaf }, { 148, 0xd7, 0x00, 0xd7 },
{ 149, 0xd7, 0x00, 0xff }, { 150, 0xd7, 0x5f, 0x00 },
{ 151, 0xd7, 0x5f, 0x5f }, { 152, 0xd7, 0x5f, 0x87 },
{ 153, 0xd7, 0x5f, 0xaf }, { 154, 0xd7, 0x5f, 0xd7 },
{ 155, 0xd7, 0x5f, 0xff }, { 156, 0xd7, 0x87, 0x00 },
{ 157, 0xd7, 0x87, 0x5f }, { 158, 0xd7, 0x87, 0x87 },
{ 159, 0xd7, 0x87, 0xaf }, { 160, 0xd7, 0x87, 0xd7 },
{ 161, 0xd7, 0x87, 0xff }, { 162, 0xd7, 0xaf, 0x00 },
{ 163, 0xd7, 0xaf, 0x5f }, { 164, 0xd7, 0xaf, 0x87 },
{ 165, 0xd7, 0xaf, 0xaf }, { 166, 0xd7, 0xaf, 0xd7 },
{ 167, 0xd7, 0xaf, 0xff }, { 168, 0xd7, 0xd7, 0x00 },
{ 169, 0xd7, 0xd7, 0x5f }, { 170, 0xd7, 0xd7, 0x87 },
{ 171, 0xd7, 0xd7, 0xaf }, { 172, 0xd7, 0xd7, 0xd7 },
{ 173, 0xd7, 0xd7, 0xff }, { 174, 0xd7, 0xff, 0x00 },
{ 175, 0xd7, 0xff, 0x5f }, { 176, 0xd7, 0xff, 0x87 },
{ 177, 0xd7, 0xff, 0xaf }, { 178, 0xd7, 0xff, 0xd7 },
{ 179, 0xd7, 0xff, 0xff }, { 237, 0xda, 0xda, 0xda },
{ 238, 0xe4, 0xe4, 0xe4 }, { 239, 0xee, 0xee, 0xee },
{ 180, 0xff, 0x00, 0x00 }, { 181, 0xff, 0x00, 0x5f },
{ 182, 0xff, 0x00, 0x87 }, { 183, 0xff, 0x00, 0xaf },
{ 184, 0xff, 0x00, 0xd7 }, { 185, 0xff, 0x00, 0xff },
{ 186, 0xff, 0x5f, 0x00 }, { 187, 0xff, 0x5f, 0x5f },
{ 188, 0xff, 0x5f, 0x87 }, { 189, 0xff, 0x5f, 0xaf },
{ 190, 0xff, 0x5f, 0xd7 }, { 191, 0xff, 0x5f, 0xff },
{ 192, 0xff, 0x87, 0x00 }, { 193, 0xff, 0x87, 0x5f },
{ 194, 0xff, 0x87, 0x87 }, { 195, 0xff, 0x87, 0xaf },
{ 196, 0xff, 0x87, 0xd7 }, { 197, 0xff, 0x87, 0xff },
{ 198, 0xff, 0xaf, 0x00 }, { 199, 0xff, 0xaf, 0x5f },
{ 200, 0xff, 0xaf, 0x87 }, { 201, 0xff, 0xaf, 0xaf },
{ 202, 0xff, 0xaf, 0xd7 }, { 203, 0xff, 0xaf, 0xff },
{ 204, 0xff, 0xd7, 0x00 }, { 205, 0xff, 0xd7, 0x5f },
{ 206, 0xff, 0xd7, 0x87 }, { 207, 0xff, 0xd7, 0xaf },
{ 208, 0xff, 0xd7, 0xd7 }, { 209, 0xff, 0xd7, 0xff },
{ 210, 0xff, 0xff, 0x00 }, { 211, 0xff, 0xff, 0x5f },
{ 212, 0xff, 0xff, 0x87 }, { 213, 0xff, 0xff, 0xaf },
{ 214, 0xff, 0xff, 0xd7 }, { 215, 0xff, 0xff, 0xff },
};
void colour_rgb_generate256(void);
u_int colour_rgb_distance(struct colour_rgb *, struct colour_rgb *);
int colour_rgb_find(struct colour_rgb *);
int colour_cmp_rgb(const void *, const void *);
/* Generate 256 colour RGB table. */
void
colour_rgb_generate256(void)
/* Compare function for bsearch(). */
int
colour_cmp_rgb(const void *lhs0, const void *rhs0)
{
struct colour_rgb *rgb;
u_int i, r, g, b;
const struct colour_rgb *lhs = lhs0, *rhs = rhs0;
/*
* 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);
if (lhs->r < rhs->r)
return (-1);
if (lhs->r > rhs->r)
return (1);
/* Add the colours first. */
r = g = b = 0;
for (i = 240; i > 24; i--) {
rgb = &colour_rgb_256[240 - i];
if (lhs->g < rhs->g)
return (-1);
if (lhs->g > rhs->g)
return (1);
if (r != 0)
rgb->r = (r * 40) + 55;
if (g != 0)
rgb->g = (g * 40) + 55;
if (b != 0)
rgb->b = (b * 40) + 55;
if (lhs->b < rhs->b)
return (-1);
if (lhs->b > rhs->b)
return (1);
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);
return (0);
}
/* Work out the nearest colour from the 256 colour set. */
int
colour_rgb_find(struct colour_rgb *rgb)
colour_find_rgb(u_char r, u_char g, u_char b)
{
u_int distance, lowest, colour, i;
struct colour_rgb rgb = { .r = r, .g = g, .b = b }, *found;
u_int distance, lowest, colour, i;
int dr, dg, db;
if (colour_rgb_256 == NULL)
colour_rgb_generate256();
found = bsearch(&rgb, colour_to_256, nitems(colour_to_256),
sizeof colour_to_256[0], colour_cmp_rgb);
if (found != NULL)
return (16 + found->i);
colour = 16;
lowest = UINT_MAX;
for (i = 0; i < 240; i++) {
distance = colour_rgb_distance(&colour_rgb_256[i], rgb);
dr = (int)colour_from_256[i].r - r;
dg = (int)colour_from_256[i].g - g;
db = (int)colour_from_256[i].b - b;
distance = dr * dr + dg * dg + db * db;
if (distance < lowest) {
lowest = distance;
colour = 16 + i;
@ -147,7 +361,7 @@ colour_tostring(int c)
static char s[32];
if (c & 0x100) {
xsnprintf(s, sizeof s, "colour%u", c & ~0x100);
xsnprintf(s, sizeof s, "colour%d", c & ~0x100);
return (s);
}
@ -194,20 +408,20 @@ colour_tostring(int c)
int
colour_fromstring(const char *s)
{
const char *errstr;
const char *cp;
struct colour_rgb rgb;
int n;
const char *errstr;
const char *cp;
int n;
u_char r, g, b;
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);
n = sscanf(s + 1, "%2hhx%2hhx%2hhx", &r, &g, &b);
if (n != 3)
return (-1);
return (colour_rgb_find(&rgb) | 0x100);
return (colour_find_rgb(r, g, b) | 0x100);
}
if (strncasecmp(s, "colour", (sizeof "colour") - 1) == 0) {
@ -217,47 +431,39 @@ colour_fromstring(const char *s)
return (n | 0x100);
}
if (strcasecmp(s, "black") == 0 || (s[0] == '0' && s[1] == '\0'))
if (strcasecmp(s, "black") == 0 || strcmp(s, "0") == 0)
return (0);
if (strcasecmp(s, "red") == 0 || (s[0] == '1' && s[1] == '\0'))
if (strcasecmp(s, "red") == 0 || strcmp(s, "1") == 0)
return (1);
if (strcasecmp(s, "green") == 0 || (s[0] == '2' && s[1] == '\0'))
if (strcasecmp(s, "green") == 0 || strcmp(s, "2") == 0)
return (2);
if (strcasecmp(s, "yellow") == 0 || (s[0] == '3' && s[1] == '\0'))
if (strcasecmp(s, "yellow") == 0 || strcmp(s, "3") == 0)
return (3);
if (strcasecmp(s, "blue") == 0 || (s[0] == '4' && s[1] == '\0'))
if (strcasecmp(s, "blue") == 0 || strcmp(s, "4") == 0)
return (4);
if (strcasecmp(s, "magenta") == 0 || (s[0] == '5' && s[1] == '\0'))
if (strcasecmp(s, "magenta") == 0 || strcmp(s, "5") == 0)
return (5);
if (strcasecmp(s, "cyan") == 0 || (s[0] == '6' && s[1] == '\0'))
if (strcasecmp(s, "cyan") == 0 || strcmp(s, "6") == 0)
return (6);
if (strcasecmp(s, "white") == 0 || (s[0] == '7' && s[1] == '\0'))
if (strcasecmp(s, "white") == 0 || strcmp(s, "7") == 0)
return (7);
if (strcasecmp(s, "default") == 0 || (s[0] == '8' && s[1] == '\0'))
if (strcasecmp(s, "default") == 0 || strcmp(s, "8") == 0)
return (8);
if (strcasecmp(s, "brightblack") == 0 ||
(s[0] == '9' && s[1] == '0' && s[1] == '\0'))
if (strcasecmp(s, "brightblack") == 0 || strcmp(s, "90") == 0)
return (90);
if (strcasecmp(s, "brightred") == 0 ||
(s[0] == '9' && s[1] == '1' && s[1] == '\0'))
if (strcasecmp(s, "brightred") == 0 || strcmp(s, "91") == 0)
return (91);
if (strcasecmp(s, "brightgreen") == 0 ||
(s[0] == '9' && s[1] == '2' && s[1] == '\0'))
if (strcasecmp(s, "brightgreen") == 0 || strcmp(s, "92") == 0)
return (92);
if (strcasecmp(s, "brightyellow") == 0 ||
(s[0] == '9' && s[1] == '3' && s[1] == '\0'))
if (strcasecmp(s, "brightyellow") == 0 || strcmp(s, "93") == 0)
return (93);
if (strcasecmp(s, "brightblue") == 0 ||
(s[0] == '9' && s[1] == '4' && s[1] == '\0'))
if (strcasecmp(s, "brightblue") == 0 || strcmp(s, "94") == 0)
return (94);
if (strcasecmp(s, "brightmagenta") == 0 ||
(s[0] == '9' && s[1] == '5' && s[1] == '\0'))
if (strcasecmp(s, "brightmagenta") == 0 || strcmp(s, "95") == 0)
return (95);
if (strcasecmp(s, "brightcyan") == 0 ||
(s[0] == '9' && s[1] == '6' && s[1] == '\0'))
if (strcasecmp(s, "brightcyan") == 0 || strcmp(s, "96") == 0)
return (96);
if (strcasecmp(s, "brightwhite") == 0 ||
(s[0] == '9' && s[1] == '7' && s[1] == '\0'))
if (strcasecmp(s, "brightwhite") == 0 || strcmp(s, "97") == 0)
return (97);
return (-1);
}
@ -287,29 +493,3 @@ colour_256to16(u_char c)
return (table[c]);
}
/* Convert 256 colour palette to 88. */
u_char
colour_256to88(u_char c)
{
static const u_char table[256] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 17, 18, 18, 19, 20, 21, 21, 22, 22, 23, 20, 21, 21, 22,
22, 23, 24, 25, 25, 26, 26, 27, 24, 25, 25, 26, 26, 27, 28, 29,
29, 30, 30, 31, 32, 33, 33, 34, 34, 35, 36, 37, 37, 38, 38, 39,
36, 37, 37, 38, 38, 39, 40, 41, 41, 42, 42, 43, 40, 41, 41, 42,
42, 43, 44, 45, 45, 46, 46, 47, 32, 33, 33, 34, 34, 35, 36, 37,
37, 38, 38, 39, 36, 37, 37, 38, 38, 39, 40, 41, 41, 42, 42, 43,
40, 41, 41, 42, 42, 43, 44, 45, 45, 46, 46, 47, 48, 49, 49, 50,
50, 51, 52, 53, 53, 54, 54, 55, 52, 53, 53, 54, 54, 55, 56, 57,
57, 58, 58, 59, 56, 57, 57, 58, 58, 59, 60, 61, 61, 62, 62, 63,
48, 49, 49, 50, 50, 51, 52, 53, 53, 54, 54, 55, 52, 53, 53, 54,
54, 55, 56, 57, 57, 58, 58, 59, 56, 57, 57, 58, 58, 59, 60, 61,
61, 62, 62, 63, 64, 65, 65, 66, 66, 67, 68, 69, 69, 70, 70, 71,
68, 69, 69, 70, 70, 71, 72, 73, 73, 74, 74, 75, 72, 73, 73, 74,
74, 75, 76, 77, 77, 78, 78, 79, 0, 0, 80, 80, 80, 81, 81, 81,
82, 82, 82, 83, 83, 83, 84, 84, 84, 85, 85, 85, 86, 86, 86, 87
};
return (table[c]);
}

View File

@ -1,5 +1,3 @@
/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
*
@ -23,6 +21,9 @@
#define __attribute__(a)
#endif
#ifndef __unused
#define __unused __attribute__ ((__unused__))
#endif
#ifndef __dead
#define __dead __attribute__ ((__noreturn__))
#endif
@ -30,6 +31,10 @@
#define __packed __attribute__ ((__packed__))
#endif
#ifndef ECHOPRT
#define ECHOPRT 0
#endif
#ifndef HAVE_BSD_TYPES
typedef uint8_t u_int8_t;
typedef uint16_t u_int16_t;
@ -121,6 +126,10 @@ typedef uint64_t u_int64_t;
#define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
#endif
#ifndef O_DIRECTORY
#define O_DIRECTORY 0
#endif
#ifndef INFTIM
#define INFTIM -1
#endif
@ -152,13 +161,31 @@ typedef uint64_t u_int64_t;
} while (0)
#endif
#ifndef timersub
#define timersub(tvp, uvp, vvp) \
do { \
(vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
(vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
if ((vvp)->tv_usec < 0) { \
(vvp)->tv_sec--; \
(vvp)->tv_usec += 1000000; \
} \
} while (0)
#endif
#ifndef TTY_NAME_MAX
#define TTY_NAME_MAX 32
#endif
#ifndef HAVE_BZERO
#undef bzero
#define bzero(buf, len) memset(buf, 0, len);
#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 255
#endif
#ifndef HAVE_FLOCK
#define LOCK_SH 0
#define LOCK_EX 0
#define LOCK_NB 0
#define flock(fd, op) (0)
#endif
#ifndef HAVE_CLOSEFROM
@ -198,6 +225,7 @@ int daemon(int, int);
#ifndef HAVE_B64_NTOP
/* b64_ntop.c */
#undef b64_ntop /* for Cygwin */
int b64_ntop(const char *, size_t, char *, size_t);
#endif
@ -218,12 +246,32 @@ int vasprintf(char **, const char *, va_list);
char *fgetln(FILE *, size_t *);
#endif
#ifndef HAVE_FPARSELN
char *fparseln(FILE *, size_t *, size_t *, const char *, int);
#endif
#ifndef HAVE_SETENV
/* setenv.c */
int setenv(const char *, const char *, int);
int unsetenv(const char *);
#endif
#ifndef HAVE_CFMAKERAW
/* cfmakeraw.c */
void cfmakeraw(struct termios *);
#endif
#ifndef HAVE_OPENAT
/* openat.c */
#define AT_FDCWD -100
int openat(int, const char *, int, ...);
#endif
#ifndef HAVE_REALLOCARRAY
/* reallocarray.c */
void *reallocarray(void *, size_t, size_t size);
#endif
#ifdef HAVE_GETOPT
#include <getopt.h>
#else

View File

@ -1,5 +1,3 @@
/* $Id$ */
/*
* Copyright (c) 2006 Nicholas Marriott <nicm@users.sourceforge.net>
*
@ -56,10 +54,12 @@ vasprintf(char **ret, const char *fmt, va_list ap)
free(*ret);
goto error;
}
va_end(ap2);
return (n);
error:
va_end(ap2);
*ret = NULL;
return (-1);
}

View File

@ -1,4 +1,3 @@
/* $Id$ */
/* $OpenBSD: bitstring.h,v 1.5 2003/06/02 19:34:12 millert Exp $ */
/* $NetBSD: bitstring.h,v 1.5 1997/05/14 15:49:55 pk Exp $ */

View File

@ -1,7 +1,6 @@
/* $Id$ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
* Copyright (c) 2013 Dagobert Michelsen
* Copyright (c) 2013 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
@ -16,28 +15,16 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <string.h>
#include "tmux.h"
/*
* Start the server and do nothing else.
*/
enum cmd_retval cmd_start_server_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_start_server_entry = {
"start-server", "start",
"", 0, 0,
"",
CMD_STARTSERVER,
NULL,
NULL,
cmd_start_server_exec
};
enum cmd_retval
cmd_start_server_exec(unused struct cmd *self, unused struct cmd_q *cmdq)
void
cfmakeraw(struct termios *tio)
{
return (CMD_RETURN_NORMAL);
tio->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
tio->c_oflag &= ~OPOST;
tio->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
tio->c_cflag &= ~(CSIZE|PARENB);
tio->c_cflag |= CS8;
}

View File

@ -1,5 +1,3 @@
/* $Id$ */
/*
* Copyright (c) 2004-2005 Todd C. Miller <Todd.Miller@courtesan.com>
*
@ -16,8 +14,6 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "tmux.h"
#ifndef HAVE_CLOSEFROM
#include <sys/types.h>
@ -49,6 +45,8 @@
# endif
#endif
#include "tmux.h"
#ifndef OPEN_MAX
# define OPEN_MAX 256
#endif

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